# OptaPlanner Workbench and Execution Server User Guide

The OptaPlanner Team <https://www.optaplanner.org/community/team.html>
version 7.66.0.Final

## 1. OptaPlanner Engine

See the OptaPlanner User Guide.

# OptaPlanner Workbench (Business Central)

## 2. Quickstart

### 2.1. Cloud Balancing Example Setup

This chapter describes the process of setting up environment to run Cloud Balancing example using Business Central and KIE Server. At the end of the chapter, the user will be able to submit sample planning problem to the KIE Server and query the best solution.

#### 2.1.1. Environment Setup

The first step consists of setting up Wildfly instance and deploying KIE artifacts.

##### 2.1.1.1. Download Required Artifacts:

- Java EE compliant application server. This example uses WildFly

- KIE Server and Business Central war files from OptaPlanner website

##### 2.1.1.2. Create New User

- Unix users:

      $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['admin', 'kie-server'])"

- Windows users:

      $WILDFLY_HOME/bin/jboss-cli.bat --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['admin', 'kie-server'])"

  - User type: application user

  - Username: planner

  - Password: Planner123_

  - Groups: kie-server,admin

##### 2.1.1.3. Deploy Business Central and KIE Server

- Copy Business Central war to `$WILDFLY_HOME/standalone/deployments/business-central.war`

- Copy KIE Server war to `$WILDFLY_HOME/standalone/deployments/kie-server.war`

##### 2.1.1.4. Start Server

- Unix users:

      ./bin/standalone.sh --server-config=standalone-full.xml \
       -Dorg.kie.server.user=planner \
       -Dorg.kie.server.pwd=Planner123_ \
       -Dorg.kie.server.controller.user=planner \
       -Dorg.kie.server.controller.pwd=Planner123_ \
       -Dorg.kie.server.id=wildfly-kieserver \
       -Dorg.kie.server.location=http://localhost:8080/kie-server/services/rest/server \
       -Dorg.kie.server.controller=http://localhost:8080/business-central/rest/controller

- Windows users:

      ./bin/standalone.bat --server-config=standalone-full.xml \
       -Dorg.kie.server.user=planner \
       -Dorg.kie.server.pwd=Planner123_ \
       -Dorg.kie.server.controller.user=planner \
       -Dorg.kie.server.controller.pwd=Planner123_ \
       -Dorg.kie.server.id=wildfly-kieserver \
       -Dorg.kie.server.location=http://localhost:8080/kie-server/services/rest/server \
       -Dorg.kie.server.controller=http://localhost:8080/business-central/rest/controller

##### 2.1.1.5. Open Business Central in Browser

Navigate to `http://localhost:8080/business-central` in a web browser to access Business Central. Use credentials defined in the previous step to log in.

#### 2.1.2. Project Setup

The second step consists of setting up logical structures required to create a new project.

##### 2.1.2.1. Create Organizational Unit

- Navigate to Authoring → Administration → Organizational Units → Manage Organizational Units and click Add

  - Name: Cloud department

  - Default Group ID: clouddepartment

##### 2.1.2.2. Create Repository

- Select Authoring → Administration → Repositories → New repository

  - Repository Name: cloudbalancing

  - In Organizational Unit: Cloud department

##### 2.1.2.3. Create Project

- Select Authoring → Project Authoring → New Project → Advanced setup

  - Project Name: cloudbalancing

  - Project Description: Assign processes to computers based on available CPU power, memory, network bandwidth and cost

  - Group ID: clouddepartment

  - Artifact ID: cloudbalancing

  - Version: 1.0

#### 2.1.3. Data Model

This step consists of creating a data model for the Cloud Balancing problem. Data objects and their attributes are defined.

##### 2.1.3.1. Create Data Object

- Select Add Asset → Data Object

  - Data Object: CloudComputer

  - Package: clouddepartment.cloudbalancing

##### 2.1.3.2. Add Fields

Add multiple fields of given types.

- Click Add field

  - id: long

  - cpuPower: int

  - memory: int

  - networkBandwith: int

  - cost: int

- Click Save

- Click Close icon

##### 2.1.3.3. Complete the Data Model

Using the same approach, create CloudProcess and CloudBalance data objects with the following attributes:

- CloudProcess

  - id: long

  - requiredCpuPower: int

  - requiredMemory: int

  - requiredNetworkBandwith: int

  - computer: clouddepartment.cloudbalancing.CloudComputer

- CloudBalance

  - id: long

  - computerList: List<clouddepartment.cloudbalancing.CloudComputer>

  - processList: List<clouddepartment.cloudbalancing.CloudProcess>

#### 2.1.4. Planner Configuration

This section explains how to enhance the data model created in the previous step with Planner annotations.

##### 2.1.4.1. CloudBalance Data Object

- Select CloudBalance

  - Open OptaPlanner dock

  - Check Planning Solution

- Select computerList field

  - Open OptaPlanner dock

  - Check Planning Value Range Provider

  - Set id to `computerRange`

- Select processList field

  - Open OptaPlanner dock

  - Check Planning Entity Collection

- Click Save

- Click Close icon

##### 2.1.4.2. CloudProcess

- Select CloudProcess

  - Open OptaPlanner dock

  - Check Planning Entity

- Select computer field

  - Open OptaPlanner dock

  - Check Planning Variable

  - Set valueRangeId to `computerRange`

- Click Save

- Click Close icon

#### 2.1.5. Drools Rules

This section contains constraint definitions for the CloudBalancing problem using two different approaches - Free-form DRL Editor and Guided Rule Editor.

##### 2.1.5.1. Free-form DRL Editor

- Select Add Asset → DRL file

  - DRL file: cloudBalancingScoreRules

  - Package: clouddepartment.cloudbalancing

        package clouddepartment.cloudbalancing;

        import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScoreHolder;

        import clouddepartment.cloudbalancing.CloudBalance;
        import clouddepartment.cloudbalancing.CloudComputer;
        import clouddepartment.cloudbalancing.CloudProcess;

        rule "requiredCpuPowerTotal"
            when
                $computer : CloudComputer($cpuPower : cpuPower)
                accumulate(
                    CloudProcess(
                        computer == $computer,
                        $requiredCpuPower : requiredCpuPower);
                    $requiredCpuPowerTotal : sum($requiredCpuPower);
                    $requiredCpuPowerTotal > $cpuPower
                )
            then
                scoreHolder.addHardConstraintMatch(kcontext, $cpuPower - $requiredCpuPowerTotal);
        end

        rule "requiredMemoryTotal"
            when
                $computer : CloudComputer($memory : memory)
                accumulate(
                    CloudProcess(
                        computer == $computer,
                        $requiredMemory : requiredMemory);
                    $requiredMemoryTotal : sum($requiredMemory);
                    $requiredMemoryTotal > $memory
                )
            then
                scoreHolder.addHardConstraintMatch(kcontext, $memory - $requiredMemoryTotal);
        end

        rule "requiredNetworkBandwidthTotal"
            when
                $computer : CloudComputer($networkBandwidth : networkBandwidth)
                accumulate(
                    CloudProcess(
                        computer == $computer,
                        $requiredNetworkBandwidth : requiredNetworkBandwidth);
                    $requiredNetworkBandwidthTotal : sum($requiredNetworkBandwidth);
                    $requiredNetworkBandwidthTotal > $networkBandwidth
                )
            then
                scoreHolder.addHardConstraintMatch(kcontext, $networkBandwidth - $requiredNetworkBandwidthTotal);
        end

- Click Save

- Click Close icon

##### 2.1.5.2. Guided Rule Editor

- Select Add Asset → Guided Rule

  - Guided Rule: computerCost

  - Package: clouddepartment.cloudbalancing

- Click Save

- Click Close icon

#### 2.1.6. Solver Configuration

The following task is to create Planner Solver configuration to tweak Planner engine parameters.

##### 2.1.6.1. Create Solver Configuration

- Select Add Asset → Solver configuration

  - Solver configuration: Cloud Balancing Solver Configuration

  - Package: clouddepartment.cloudbalancing

  - Navigate to Termination

    - Click Add and select Time spent

    - Set Seconds to `30` to stop the solving process after 30 seconds

- Click Save

- Click Close icon

#### 2.1.7. Build & Deploy

##### 2.1.7.1. Add Kie Container

- Navigate to Deploy → Execution Servers and click Add Container

  - Name: cloudbalancing

  - Group Name: clouddepartment

  - Artifact Id: cloudbalancing

  - Version: 1.0

##### 2.1.7.2. Build Project

- Navigate to Authoring → Project Authoring → cloudbalancing and click Build & Deploy

##### 2.1.7.3. Start Container

- Navigate to Deploy → Execution Servers

  - Select container cloudbalancing and click Start

#### 2.1.8. KIE Server Integration

This section describes basic steps required to set up Planner & KIE Server integration. A sample Cloud Balancing problem instance is submitted to the KIE Server and the result is queried using REST API the server exposes.

All HTTP requests performed in this chapter use the following header:

    authorization: Basic cGxhbm5lcjpQbGFubmVyMTIzXw==
    X-KIE-ContentType: xstream
    content-type: application/xml

##### 2.1.8.1. Register Solver

- `PUT http://localhost:8080/kie-server/services/rest/server/containers/cloudbalancing/solvers/cloudBalancingSolver`

  Request body

      <solver-instance>
        <solver-config-file>clouddepartment/cloudbalancing/Cloud Balancing Solver Configuration.solver.xml</solver-config-file>
      </solver-instance>

##### 2.1.8.2. Submit Solution

- `POST http://localhost:8080/kie-server/services/rest/server/containers/cloudbalancing/solvers/cloudBalancingSolver/state/solving`

  Request body

      <planning-problem class="clouddepartment.cloudbalancing.CloudBalance" id="1">
        <id>0</id>
        <computerList id="2">
          <clouddepartment.cloudbalancing.CloudComputer id="3">
            <id>0</id>
            <cpuPower>24</cpuPower>
            <memory>96</memory>
            <networkBandwidth>16</networkBandwidth>
            <cost>4800</cost>
          </clouddepartment.cloudbalancing.CloudComputer>
          <clouddepartment.cloudbalancing.CloudComputer id="4">
            <id>1</id>
            <cpuPower>6</cpuPower>
            <memory>4</memory>
            <networkBandwidth>6</networkBandwidth>
            <cost>660</cost>
          </clouddepartment.cloudbalancing.CloudComputer>
        </computerList>
        <processList id="5">
          <clouddepartment.cloudbalancing.CloudProcess id="6">
            <id>0</id>
            <requiredCpuPower>1</requiredCpuPower>
            <requiredMemory>1</requiredMemory>
            <requiredNetworkBandwidth>1</requiredNetworkBandwidth>
          </clouddepartment.cloudbalancing.CloudProcess>
          <clouddepartment.cloudbalancing.CloudProcess id="7">
            <id>1</id>
            <requiredCpuPower>3</requiredCpuPower>
            <requiredMemory>6</requiredMemory>
            <requiredNetworkBandwidth>1</requiredNetworkBandwidth>
          </clouddepartment.cloudbalancing.CloudProcess>
          <clouddepartment.cloudbalancing.CloudProcess id="8">
            <id>2</id>
            <requiredCpuPower>1</requiredCpuPower>
            <requiredMemory>1</requiredMemory>
            <requiredNetworkBandwidth>3</requiredNetworkBandwidth>
          </clouddepartment.cloudbalancing.CloudProcess>
          <clouddepartment.cloudbalancing.CloudProcess id="9">
            <id>3</id>
            <requiredCpuPower>1</requiredCpuPower>
            <requiredMemory>2</requiredMemory>
            <requiredNetworkBandwidth>11</requiredNetworkBandwidth>
          </clouddepartment.cloudbalancing.CloudProcess>
          <clouddepartment.cloudbalancing.CloudProcess id="10">
            <id>4</id>
            <requiredCpuPower>1</requiredCpuPower>
            <requiredMemory>1</requiredMemory>
            <requiredNetworkBandwidth>1</requiredNetworkBandwidth>
          </clouddepartment.cloudbalancing.CloudProcess>
          <clouddepartment.cloudbalancing.CloudProcess id="11">
            <id>5</id>
            <requiredCpuPower>1</requiredCpuPower>
            <requiredMemory>1</requiredMemory>
            <requiredNetworkBandwidth>5</requiredNetworkBandwidth>
          </clouddepartment.cloudbalancing.CloudProcess>
        </processList>
      </planning-problem>

##### 2.1.8.3. Query Best Solution

- `GET http://localhost:8080/kie-server/services/rest/server/containers/cloudbalancing/solvers/cloudBalancingSolver/bestsolution`

  - Verify that the `computer` attributes of `CloudProcess` instances are assigned

## 3. Business Central (General)

### 3.1. Installation

#### 3.1.1. War installation

Use the `war` from the Business Central distribution zip that corresponds to your application server. The differences between these `war` files are mainly superficial. For example, some JARs might be excluded if the application server already supplies them.

- `eap7`: tailored for Red Hat JBoss Enterprise Application Platform 7

- `wildfly14`: tailored for Wildfly 14

#### 3.1.2. Business Central data

Business Central stores its data, by default in the directory `$WORKING_DIRECTORY/.niogit`, for example `wildfly-14.0.1.Final/bin/.niogit`, but it can be overridden with the system property`-Dorg.uberfire.nio.git.dir`.

| In production, make sure to back up the Business Central data directory.

#### 3.1.3. Troubleshooting

##### 3.1.3.1. Loading.. does not disappear and Business Central fails to show

There have been reports that Firewalls in between the server and the browser can interfere with Server Sent Events (SSE) used by Business Central.

The issue results in the "Loading…​" spinner remaining visible and Business Central failing to materialize.

The workaround is to disable the Business Central’s use of Server Sent Events by adding file `/WEB-INF/classes/ErraiService.properties` to the exploded WAR containing the value `errai.bus.enable_sse_support=false`. Re-package the WAR and re-deploy.

Some Users have also reported disabling Server Sent Events does not resolve the issue. The solution found to work is to configure the JVM to use a different Entropy Gathering Device on Linux for `SecureRandom`. This can be configured by setting System Property `java.security.egd` to `file:/dev/./urandom`. See this Stack Overflow post for details.

Please note however this affects the JVM’s random number generation and may present other challenges where strong cryptography is required. Configure with caution.

##### 3.1.3.2. Not able to clone Business Central Git repository using ssh protocol.

Git clients using ssh to interact with the Git server that is bundled with Business Central are authenticated and authorized to perform git commands by the security API that is part of the Uberfire backend server. When using an LDAP security realm, some git clients were not being authorized as expected. This was due to the fact that for non-web clients such as Git via ssh, the principal (i.e., user or group) name assigned to a user by the application server’s user registry is the more complex DN associated to that principal by LDAP. The logic of the Uberfire backend server looked for on exact match of roles allowed with the principal name returned and therefore failed.

It is now possible to control the role-principal matching via the system property

    org.uberfire.ldap.regex.role_mapper

which takes as its value a Regex pattern to be applied when matching LDAP principal to role names. The pattern must contain the literal word variable 'role'. During authorization the variable is replaced by each of the allow application roles. If the pattern is matched the role is added to the user.

For instance, if the DN for the admin group in LDAP is

    DN: cn=admin,ou=groups,dc=example,dc=com

and its intended role is admin, then setting `org.uberfire.ldap.regex.role_mapper` with value

    cn[\\ ]*=[\\ ]*role

will find a match on role 'admin'.

### 3.2. Business Central system properties

The Business Central system properties listed in this section are passed to `standalone*.xml` files.

Git directory

  Use the following properties to set the location and name for the Business Central Git directory:

  - `org.uberfire.nio.git.dir`: Location of the Business Central Git directory.

  - `org.uberfire.nio.git.dirname`: Name of the Business Central Git directory. Default value: `.niogit`.

  - `org.uberfire.nio.git.ketch`: Enables or disables Git ketch.

  - `org.uberfire.nio.git.hooks`: Location of the Git hooks directory.

Git over HTTP

  Use the following properties to configure access to the Git repository over HTTP:

  - `org.uberfire.nio.git.proxy.ssh.over.http`: Specifies whether SSH should use an HTTP proxy. Default value: `false`.

  - `http.proxyHost`: Defines the host name of the HTTP proxy. Default value: `null`.

  - `http.proxyPort`: Defines the host port (integer value) of the HTTP proxy. Default value: `null`.

  - `http.proxyUser`: Defines the user name of the HTTP proxy.

  - `http.proxyPassword`: Defines the user password of the HTTP proxy.

  - `org.uberfire.nio.git.http.enabled`: Enables or disables the HTTP daemon. Default value: `true`.

  - `org.uberfire.nio.git.http.host`: If the HTTP daemon is enabled, it uses this property as the host identifier. This is an informative property that is used to display how to access the Git repository over HTTP. The HTTP still relies on the servlet container. Default value: `localhost`.

  - `org.uberfire.nio.git.http.hostname`: If the HTTP daemon is enabled, it uses this property as the host name identifier. This is an informative property that is used to display how to access the Git repository over HTTP. The HTTP still relies on the servlet container. Default value: `localhost`.

  - `org.uberfire.nio.git.http.port`: If the HTTP daemon is enabled, it uses this property as the port number. This is an informative property that is used to display how to access the Git repository over HTTP. The HTTP still relies on the servlet container. Default value: `8080`.

Git over HTTPS

  Use the following properties to configure access to the Git repository over HTTPS:

  - `org.uberfire.nio.git.proxy.ssh.over.https`: Specifies whether SSH uses an HTTPS proxy. Default value: `false`.

  - `https.proxyHost`: Defines the host name of the HTTPS proxy. Default value: `null`.

  - `https.proxyPort`: Defines the host port (integer value) of the HTTPS proxy. Default value: `null`.

  - `https.proxyUser`: Defines the user name of the HTTPS proxy.

  - `https.proxyPassword`: Defines the user password of the HTTPS proxy.

  - `user.dir`: Location of the user directory.

  - `org.uberfire.nio.git.https.enabled`: Enables or disables the HTTPS daemon. Default value: `false`

  - `org.uberfire.nio.git.https.host`: If the HTTPS daemon is enabled, it uses this property as the host identifier. This is an informative property that is used to display how to access the Git repository over HTTPS. The HTTPS still relies on the servlet container. Default value: `localhost`.

  - `org.uberfire.nio.git.https.hostname`: If the HTTPS daemon is enabled, it uses this property as the host name identifier. This is an informative property that is used to display how to access the Git repository over HTTPS. The HTTPS still relies on the servlet container. Default value: `localhost`.

  - `org.uberfire.nio.git.https.port`: If the HTTPS daemon is enabled, it uses this property as the port number. This is an informative property that is used to display how to access the Git repository over HTTPS. The HTTPS still relies on the servlet container. Default value: `8080`.

JGit

  - `org.uberfire.nio.jgit.cache.instances`: Defines the JGit cache size.

  - `org.uberfire.nio.jgit.cache.overflow.cleanup.size`: Defines the JGit cache overflow cleanup size.

  - `org.uberfire.nio.jgit.remove.eldest.iterations`: Enables or disables whether to remove eldest JGit iterations.

  - `org.uberfire.nio.jgit.cache.evict.threshold.duration`: Defines the JGit evict threshold duration.

  - `org.uberfire.nio.jgit.cache.evict.threshold.time.unit`: Defines the JGit evict threshold time unit.

Git daemon

  Use the following properties to enable and configure the Git daemon:

  - `org.uberfire.nio.git.daemon.enabled`: Enables or disables the Git daemon. Default value: `true`.

  - `org.uberfire.nio.git.daemon.host`: If the Git daemon is enabled, it uses this property as the local host identifier. Default value: `localhost`.

  - `org.uberfire.nio.git.daemon.hostname`: If the Git daemon is enabled, it uses this property as the local host name identifier. Default value: `localhost`

  - `org.uberfire.nio.git.daemon.port`: If the Git daemon is enabled, it uses this property as the port number. Default value: `9418`.

  - `org.uberfire.nio.git.http.sslVerify`: Enables or disables SSL certificate checking for Git repositories. Default value: `true`.

    | If the default or assigned port is already in use, a new port is automatically selected. Ensure that the ports are available and check the log for more information.

Git SSH

  Use the following properties to enable and configure the Git SSH daemon:

  - `org.uberfire.nio.git.ssh.enabled`: Enables or disables the SSH daemon. Default value: `true`.

  - `org.uberfire.nio.git.ssh.host`: If the SSH daemon enabled, it uses this property as the local host identifier. Default value: `localhost`.

  - `org.uberfire.nio.git.ssh.hostname`: If the SSH daemon is enabled, it uses this property as local host name identifier. Default value: `localhost`.

  - `org.uberfire.nio.git.ssh.port`: If the SSH daemon is enabled, it uses this property as the port number. Default value: `8001`.

    | If the default or assigned port is already in use, a new port is automatically selected. Ensure that the ports are available and check the log for more information.

  - `org.uberfire.nio.git.ssh.cert.dir`: Location of the `.security` directory where local certificates are stored. Default value: Working directory.

  - `org.uberfire.nio.git.ssh.idle.timeout`: Sets the SSH idle timeout.

  - `org.uberfire.nio.git.ssh.passphrase`: Pass phrase used to access the public key store of your operating system when cloning git repositories with SCP style URLs. Example: `git@github.com:user/repository.git`.

  - `org.uberfire.nio.git.ssh.algorithm`: Algorithm used by SSH. Default value: `RSA`.

  - `org.uberfire.nio.git.gc.limit`: Sets the GC limit.

  - `org.uberfire.nio.git.ssh.ciphers`: A comma-separated string of ciphers. The available ciphers are `aes128-ctr`, `aes192-ctr`, `aes256-ctr`, `arcfour128`, `arcfour256`, `aes192-cbc`, `aes256-cbc`. If the property is not used, all available ciphers are loaded.

  - `org.uberfire.nio.git.ssh.macs`: A comma-separated string of message authentication codes (MACs). The available MACs are `hmac-md5`, `hmac-md5-96`, `hmac-sha1`, `hmac-sha1-96`, `hmac-sha2-256`, `hmac-sha2-512`. If the property is not used, all available MACs are loaded.

    | If you plan to use RSA or any algorithm other than DSA, make sure you set up your application server to use the Bouncy Castle JCE library.

KIE Server nodes and KIE Server controller

  Use the following properties to configure the connections with the KIE Server nodes from the KIE Server controller:

  - `org.kie.server.controller`: The URL is used to connect to the KIE Server controller. For example, `ws://localhost:8080/business-central/websocket/controller`.

  - `org.kie.server.user`: User name used to connect to the KIE Server nodes from the KIE Server controller. This property is only required when using this Business Central installation as a KIE Server controller.

  - `org.kie.server.pwd`: Password used to connect to the KIE Server nodes from the KIE Server controller. This property is only required when using this Business Central installation as a KIE Server controller.

Maven and miscellaneous

  Use the following properties to configure Maven and other miscellaneous functions:

  - `kie.maven.offline.force`: Forces Maven to behave as if offline. If true, disables online dependency resolution. Default value: `false`.

    | Use this property for Business Central only. If you share a runtime environment with any other component, isolate the configuration and apply it only to Business Central.

  - `org.uberfire.gzip.enable`: Enables or disables Gzip compression on the `GzipFilter` compression filter. Default value: `true`.

  - `org.kie.workbench.profile`: Selects the Business Central profile. Possible values are `FULL` or `PLANNER_AND_RULES`. A prefix `FULL_` sets the profile and hides the profile preferences from the administrator preferences. Default value: `FULL`

  - `org.appformer.m2repo.url`: Business Central uses the default location of the Maven repository when looking for dependencies. It directs to the Maven repository inside Business Central, for example, `http://localhost:8080/business-central/maven2`. Set this property before starting Business Central. Default value: File path to the inner `m2` repository.

  - `appformer.ssh.keystore`: Defines the custom SSH keystore to be used with Business Central by specifying a class name. If the property is not available, the default SSH keystore is used.

  - `appformer.ssh.keys.storage.folder`: When using the default SSH keystore, this property defines the storage folder for the user’s SSH public keys. If the property is not available, the keys are stored in the Business Central `.security` folder.

  - `appformer.experimental.features`: Enables the experimental features framework. Default value: `false`.

  - `org.kie.demo`: Enables an external clone of a demo application from GitHub.

  - `org.uberfire.metadata.index.dir`: Place where the Lucene `.index` directory is stored. Default value: Working directory.

  - `org.uberfire.ldap.regex.role_mapper`: Regex pattern used to map LDAP principal names to the application role name. Note that the variable role must be a part of the pattern as the application role name substitutes the variable role when matching a principle value and role name.

  - `org.uberfire.sys.repo.monitor.disabled`: Disables the configuration monitor. Do not disable unless you are sure. Default value: `false`.

  - `org.uberfire.secure.key`: Password used by password encryption. Default value: `org.uberfire.admin`.

  - `org.uberfire.secure.alg`: Crypto algorithm used by password encryption. Default value: `PBEWithMD5AndDES`.

  - `org.uberfire.domain`: Security-domain name used by uberfire. Default value: `ApplicationRealm`.

  - `org.guvnor.m2repo.dir`: Place where the Maven repository folder is stored. Default value: `<working-directory>/repositories/kie`.

  - `org.guvnor.project.gav.check.disabled`: Disables group ID, artifact ID, and version (GAV) checks. Default value: `false`.

  - `org.kie.build.disable-project-explorer`: Disables automatic build of a selected project in Project Explorer. Default value: `false`.

  - `org.kie.builder.cache.size`: Defines the cache size of the project builder. Default value: `20`.

  - `org.kie.library.assets_per_page`: You can customize the number of assets per page in the project screen. Default value: `15`.

  - `org.kie.verification.disable-dtable-realtime-verification`: Disables the real-time validation and verification of decision tables. Default value: `false`.

KIE Server controller

  Use the following properties to configure how to connect to the KIE Server controller:

  - `org.kie.workbench.controller`: The URL used to connect to the KIE Server controller, for example, `ws://localhost:8080/kie-server-controller/websocket/controller`.

  - `org.kie.workbench.controller.user`: The KIE Server controller user. Default value: `kieserver`.

  - `org.kie.workbench.controller.pwd`: The KIE Server controller password. Default value: `kieserver1!`.

  - `org.kie.workbench.controller.token`: The token string used to connect to the KIE Server controller.

Java Cryptography Extension KeyStore (JCEKS)

  Use the following properties to configure JCEKS:

  - `kie.keystore.keyStoreURL`: The URL used to load a Java Cryptography Extension KeyStore (JCEKS). For example, `file:///home/kie/keystores/keystore.jceks.`

  - `kie.keystore.keyStorePwd`: The password used for the JCEKS.

  - `kie.keystore.key.ctrl.alias`: The alias of the key for the default REST KIE Server controller.

  - `kie.keystore.key.ctrl.pwd`: The password of the alias for the default REST KIE Server controller.

Rendering

  Use the following properties to switch between Business Central and KIE Server rendered forms:

  - `org.jbpm.wb.forms.renderer.ext`: Switches the form rendering between Business Central and KIE Server. By default, the form rendering is performed by Business Central. Default value: `false`.

  - `org.jbpm.wb.forms.renderer.name`: Enables you to switch between Business Central and KIE Server rendered forms. Default value: `workbench`.

### 3.3. Quick Start

These steps help you get started with minimum of effort.

They should not be a substitute for reading the documentation in full.

#### 3.3.1. Importing examples

Import Examples - Quick install examples

If Business Central is empty you are shown an empty Space page. Clicking "Try Samples" button below will show the examples that are available.

Once "Try Samples" page opens, you can select one or more examples and click "Ok".

If Business Central already contains Projects the examples can be imported with the "Try Samples" button found from the menu.

#### 3.3.2. Add Project

Alternatively, to importing an example, a new empty project can be created from the Space page with "Add Project".

Figure 1. New Project button

Give the Project a name and optional description.

Figure 2. Giving Project a name

#### 3.3.3. Define Data Model

After a Project has been created you need to define Types to be used by your rules.

Select "Data Object" from the "Add Asset" menu.

| You can also use types contained in existing JARs. Please consult the full documentation for details.

Figure 3. Creating "Data Object"

Set the name and select a package for the new type.

Figure 4. Creating a new type

Click "+ add field" button and set a field name and type and click "Create" to create a field for the type.

Figure 5. Click "Create" and add the field

Click "Save" to update the model.

Figure 6. Clicking "Save"

#### 3.3.4. Define Rule

Select "DRL file" (for example) from the "Add Asset" menu.

Figure 7. Selecting "DRL file" from the "Add Asset" menu

Enter a file name for the new rule.

| Make sure you select the same package as the rule had. It is possible to have rules and data models in different packages, but let’s keep things simple for demo purposes.

Figure 8. Entering a file name for rule

Enter a definition for the rule.

The definition process differs from asset type to asset type.

The full documentation has details about the different editors.

Figure 9. Defining a rule

Once the rule has been defined it will need to be saved in the same way we saved the model.

#### 3.3.5. Build and Deploy

Once rules have been defined within a project; the project can be built and deployed to the Business Central’s Maven Artifact Repository.

To build a project select the "Build & Deploy" from the Project Authoring.

Figure 10. Building a project

Click "Build & Deploy" to build the project and deploy it to the Business Central’s Maven Artifact Repository.

When you select Build & Deploy Business Central will deploy to any repositories defined in the Dependency Management section of the pom in your Business Central project. You can edit the pom.xml file associated with your Business Central project under the Repository View of the project explorer. Details on dependency management in maven can be found here : http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

If there are errors during the build process they will be reported in the "Messages" panel.

Now the project has been built and deployed; it can be referenced from your own projects as any other Maven Artifact.

The full documentation contains details about integrating projects with your own applications.

### 3.4. Configuration

#### 3.4.1. Basic user management

Business Central authenticates its users against the application server’s authentication and authorization (JAAS).

On JBoss EAP and WildFly, add a user with the script `jboss-cli.sh` (or `.bat`):

    $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['admin'])"

There is no need to restart the application server.

#### 3.4.2. Roles

Business Central uses the following roles:

- admin

- analyst

- developer

- manager

- user

##### 3.4.2.1. Admin

Administrates the BPMS system.

- Manages users

- Manages VFS Repositories

- Has full access to make any necessary changes

##### 3.4.2.2. Developer

Developer can do almost everything admin can do, except clone repositories.

- Manages rules, models, process flows, forms and dashboards

- Manages the asset repository

- Can create, build and deploy projects

- Can use the JBDS connection to view processes

##### 3.4.2.3. Analyst

Analyst is a weaker version of developer and does not have access to the asset repository or the ability to deploy projects.

##### 3.4.2.4. Business user

Daily user of the system to take actions on business tasks that are required for the processes to continue forward. Works primarily with the task lists.

- Does process management

- Handles tasks and dashboards

##### 3.4.2.5. Manager/Viewer-only User

Viewer of the system that is interested in statistics around the business processes and their performance, business indicators, and other reporting of the system and people who interact with the system.

- Only has access to dashboards

### 3.5. Introduction

#### 3.5.1. Log in and log out

Create a user with the role `admin` and log in with those credentials.

After successfully logging in, the account user name is displayed at the top right. Click it to review the roles of the current account.

#### 3.5.2. Home screen

After logging in, the home screen shows. The actual content of the home screen depends on the Business Central variant (Drools, jBPM, …​).

#### 3.5.3. Business Central overview

Business Central is structured with Spaces and Projects:

##### 3.5.3.1. Space

Spaces are useful to model departments and divisions.

A Space can hold multiple Projects.

##### 3.5.3.2. Project

Projects are the place where assets are stored and each project belongs to a single Space.

Projects are in fact a Virtual File System based storage, that by default uses GIT as backend. Such setup allows Business Central to work with multiple backends and, at the same time, take full advantage of backend specifics features like in GIT case versioning, branching and even external access.

A new Project can be created from scratch or cloned from an existing repository.

One of the biggest advantages of using GIT as backend is the ability to clone a repository from external and use your preferred tools to edit and build your assets.

| Never clone your repositories directly from .niogit directory.

#### 3.5.4. Business Central user interface concepts

Business Central consists of different logical entities:

- Part

  A Part is a screen or editor with which the user can interact to perform operations.

  Example Parts are "Project Explorer", "Project Editor", "Guided Rule Editor" etc.

- Page

  A perspective is a logical grouping of related Panels and Parts. A perspective is usually named as page, since it is a term far more familiar to end users whereas a perspective is more developer oriented. Notice however, Business Central supports both developer created pages and those created by end users from the page builder (aka Content Management) tooling but, generally speaking, page is used to refer to both of them.

  The user can switch between pages by clicking on one of the top-level menu items; such as "Home", "Authoring", "Deploy" etc.

### 3.6. Customizing project preferences

In Business Central, a project is a part of your space and stores the related assets. You can add multiple projects in a space.

For example, an organization includes various departments, such as HR, Payroll, Engineering, and R&D. You can map each department to a space in Business Central, along with adding respective projects.

You can customize the project settings in Business Central. Also, you can create a new project or clone projects from an existing Git repository.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner and select Projects.

2. In the Project Preferences panel, select the preference you want to modify. The project preferences include:

   - Project Importing: This preference consists of the following property:

     - Select the Allow multiple projects to be imported on cluster to import multiple projects on a cluster.

   - File exporting: This preference consists of the following properties:

     Table 1. File exporting properties
     Field | Description
     --- | ---
     PDF orientation | Determines whether the PDF orientation is portrait or landscape.
     PDF units | Determines whether the PDF unit is PT, MM, CN, or IN.
     PDF page format | Determines whether the PDF page format is A[0-10], B[0-10], or C[0-10].

   - Spaces: This preference consists of the following properties:

     Table 2. Spaces properties
     Field | Description
     --- | ---
     Name | The default name of the space that is created automatically if none exists.
     Owner | The default owner of the space that is created automatically if none exists.
     Group ID | The default group ID of the space that is created automatically if none exists.
     Alias (in singular) | Determines the customized alias (singular) of the space.
     Alias (in plural) | Determines the customized alias (plural) of the space.

   - Default values: This preference consists of the following properties:

     Table 3. Default values properties
     Field | Description
     --- | ---
     Version | The default version number of a project when creating projects.
     Description | The default description of a project when creating projects.
     Branch | The default branch to be used when using a Git repository.
     Assets Per Page | Used to customize the number of assets per page in the project. The default value is `15`.

   - Advanced GAV preferences: This preference consists of the following properties:

     Table 4. Advanced GAV preference properties
     Field | Description
     --- | ---
     Disable GAV conflict check? | Determines whether to enable or disable the GAV conflict check. Disabling this checkbox enables the projects to contain the same GAV (group ID, artifact, and version).
     Allow child GAV edition? | Determines whether to allow child or subprojects to contain GAV edition.

     | Duplicate GAV detection is disabled for projects in the development mode. To enable duplicate GAV detection for a project in Business Central, go to project Settings → General Settings → Version and toggle the Development Mode option to OFF (if applicable).

3. Click Save.

### 3.7. Changing the layout

#### 3.7.1. Resizing

Move the mouse pointer over the panel splitter (a grey horizontal or vertical line in between panels).

The cursor will by changing indicate it is positioned correctly over the splitter. Press and hold the left mouse button and drag the splitter to the required position; then release the left mouse button.

### 3.8. Authoring (General)

#### 3.8.1. Artifact Repository

Projects often need external artifacts in their classpath in order to build, for example a domain model JARs. The artifact repository holds those artifacts.

The Artifact Repository is a full blown Maven repository. It follows the semantics of a Maven remote repository: all snapshots are timestamped. But it is often stored on the local hard drive.

By default the artifact repository is stored under `$WORKING_DIRECTORY/repositories/kie`, but it can be overridden with the system property`-Dorg.guvnor.m2repo.dir`. There is only 1 Maven repository per installation.

The Artifact Repository screen shows a list of the artifacts in the Maven repository:

To add a new artifact to that Maven repository, either:

- Use the upload button and select a JAR. If the JAR contains a POM file under `META-INF/maven` (which every JAR build by Maven has), no further information is needed. Otherwise, a groupId, artifactId and version need to be given too.

- Using Maven, `mvn deploy` to that Maven repository. Refresh the list to make it show up.

| This remote Maven repository is relatively simple. It does not support proxying, mirroring, …​ like Nexus or Archiva.

#### 3.8.2. Asset Editor

The Asset Editor is the principle component of the Business Central user interface. It consists of two main views Editor and Overview.

- The views

  Figure 11. The Asset Editor - Editor tab

  - A : The editing area - exactly what form the editor takes depends on the Asset type. An asset can only be edited by one user at a time to avoid conflicts. When a user begins to edit an asset, a lock will automatically be acquired. This is indicated by a lock symbol appearing on the asset title bar as well as in the project explorer view (see Project Explorer for details). If a user starts editing an already locked asset a pop-up notification will appear to inform the user that the asset can’t currently be edited, as it is being worked on by another user. Changes will be prevented until the editing user saves or closes the asset, or logs out of Business Central. Session timeouts will also cause locks to be released. Every user further has the option to force a lock release, if required (see the Metadata section below).

  - B : This menu bar contains various actions for the Asset; such as Save, Rename, Copy etc. Note that saving, renaming and deleting are deactivated if the asset is locked by a different user.

  - C : Different views for asset content or asset information.

    - Editor shows the main editor for the asset

    - Overview contains the metadata and conversation views for this editor. Explained in more detail below.

    - Source shows the asset in plain DRL. Note: This tab is only visible if the asset content can be generated into DRL.

    - Data Objects contains the model available for authoring. By default only Data Objects that reside within the same package as the asset are available for authoring. Data Objects outside of this package can be imported to become available for authoring the asset.

  Figure 12. The Asset Editor - Data Objects tab

- Overview

  - A : General information about the asset and the asset’s description.

    "Type:" The format name of the type of Asset.

    "Description:" Description for the asset.

    "Used in projects:" Names the projects where this rule is used.

    "Last Modified:" Who made the last change and when.

    "Created on:" Who created the asset and when.

  - B : Version history for the asset. Selecting a version loads the selected version into this editor.

  - C : Meta data (from the "Dublin Core" standard)

  - D : Comments regarding the development of the Asset can be recorded here.

Figure 13. The Asset Editor - Overview tab

- Metadata

  - A : Meta data:-

    "Tags:" A tagging system for grouping the assets.

    "Note:" A comment made when the Asset was last updated (i.e. why a change was made)

    "URI:" URI to the asset inside the Git repository.

    "Subject/Type/External link/Source" : Other miscellaneous meta data for the Asset.

    "Lock status" : Shows the lock status of the asset and, if locked, allows to force unlocking the asset.

Figure 14. The Metadata tab

- Locking

  Business Central supports pessimistic locking of assets. When one User starts editing an asset it is locked to change by other Users. The lock is held until a period of inactivity lapses, the Editor is closed or the application stopped and restarted. Locks can also be forcibly removed on the MetaData section of the Overview tab.

  A "padlock" icon is shown in the Editor’s title bar and beside the asset in the Project Explorer when an asset is locked.

  Figure 15. The Asset Editor - Locked assets cannot be edited by other users

#### 3.8.3. Tags Editor

Tags allow assets to be labelled with any number of tags that you define. These tags can be used to filter assets on the Project Explorer enabling "Tag filtering".

##### 3.8.3.1. Creating Tags

To create tags you simply have to write them on the Tags input and press the "Add new Tag/s" button. The Tag Editor allows creating tags one by one or writing more than one separated with a white space.

Figure 16. Creating Tags

Once you created new Tags they will appear over the Editor allowing you to remove them by pressing on them if you want.

Figure 17. Existing Tags

#### 3.8.4. Project Explorer

The Project Explorer provides the ability to browse files inside the current Project. The Project Explorer can be accessed from the left side when an Asset Editor is open.

##### 3.8.4.1. Initial view

If a file is currently being edited by another user, a lock symbol will be displayed in front of the file name. The symbol is blue in case the lock is owned by the currently authenticated user, otherwise black. Moving the mouse pointer over the lock symbol will display a tooltip providing the name of the user who is currently editing the file (and therefore owning the lock). To learn more about locking see Asset Editor for details.

Figure 18. Expanded asset group

##### 3.8.4.2. Different views

Project Explorer supports multiple views.

- Project View

  A simplified view of the underlying project structure. Certain system files are hidden from view.

- Repository View

  A complete view of the underlying project structure including all files; either user-defined or system generated.

Views can be selected by clicking on the icon within the Project Explorer, as shown below.

Both Project and Repository Views can be further refined by selecting either "Show as Folders" or "Show as Links".

Figure 19. Switching view

###### Repository View examples

Figure 20. Repository View - Folders
Figure 21. Repository View - Links

##### 3.8.4.3. Download Project or Repository

"Download Project" or "Download Repository" make it possible to download the project or the repository as a ZIP file.

Figure 22. Repository and Project Downloads

##### 3.8.4.4. Filtering by Tag

Viewing elements in packages that contain a lot of assets easily is now made possible by enabling the Tag filter, which allows you to filter assets by their tags.

To see how to add tags to an asset look at: Tags Editor

Figure 23. Enabling Filter by Tag
Figure 24. Filter by Tag
Figure 25. Filtering by Tag

##### 3.8.4.5. Copy, Rename, Delete and Download Actions

Copy, rename and delete actions are available on Links mode, for packages in of Project View and for files and directories in the Repository View. Download action is available for directories. Download option downloads the selected the selected directory as a zip file.

- A : Copy

- B : Rename

- C : Delete

- D : Download

Figure 26. Project View - Package actions

| Business Central roadmap includes a refactoring and an impact analysis tool, but currently doesn’t have it. Until both tools are provided make sure that your changes (copy/rename/delete) on packages, files or directories doesn’t have a major impact on your project. In cases that your change had an unexpected impact, Business Central enables you to restore your repository using the Repository editor.

| Files locked by other users as well as directories that contain such files cannot be renamed or deleted until the corresponding locks are released. If that is the case the rename and delete symbols will be deactivated. To learn more about locking see Asset Editor for details.

#### 3.8.5. Project Editor

The Project Editor screen can be accessed from Project Explorer. Project Editor shows the settings for the currently active project.

Unlike most of the Business Central editors, project editor edits more than one file. Showing everything that is needed for configuring the KIE project in one place.

Figure 27. Project Screen and the different views

##### 3.8.5.1. Build & Deploy

Build & Deploy builds the current project and deploys the KJAR into the Business Central internal Maven repository.

##### 3.8.5.2. Project Settings

Project Settings edits the pom.xml file used by Maven.

###### Project General Settings

General settings provide tools for project name and GAV-data (Group, Artifact, Version). GAV values are used as identifiers to differentiate projects and versions of the same project.

Figure 28. Project Settings

###### Dependencies

The project may have any number of either internal or external dependencies. Dependency is a project that has been built and deployed to a Maven repository. Internal dependencies are projects built and deployed in the same Business Central as the project. External dependencies are retrieved from repositories outside of the current Business Central. Each dependency uses the GAV-values to specify the project name and version that is used by the project.

Figure 29. Dependencies
Package Name White List

Classes and declared types in white listed packages show up as Data Objects that can be imported in assets. The full list is stored in package-name-white-list file that is stored in each project root.

Package white list has three modes:

- All packages included: Every package defined in this jar is white listed.

- Packages not included: None of the packages listed in this jar are white listed.

- Some packages included: Only part of the packages in the jar are white listed.

###### Metadata

Metadata for the pom.xml file.

##### 3.8.5.3. KIE base Settings

KIE base Settings edits the kmodule.xml file used by Drools.

Figure 30. KIE base Settings

| For more information about the KIE base properties, check the Drools Expert documentation for kmodule.xml.

###### KIE bases and sessions

KIE bases and sessions lists the KIE bases and the KIE sessions specified for the project.

KIE base list

Lists all the KIE bases by name. Only one KIE base can be set as default.

KIE base properties

KIE base can include other KIE bases. The models, rules and any other content in the included KIE base will be visible and usable by the currently selected KIE base.

Rules and models are stored in packages. The packages property specifies what packages are included into this KIE base.

Equals behavior is explained in the Drools Expert part of the documentation.

Event processing mode is explained in the Drools Fusion part of the documentation.

KIE sessions

The table lists all the KIE sessions in the selected KIE base. There can be only one default of each type. The types are stateless and stateful. Clicking the pen-icon opens a popup that shows more properties for the KIE session.

###### Metadata

Metadata for the kmodule.xml

##### 3.8.5.4. Imports

Settings edits the `project.imports` file used by the Business Central editors.

Figure 31. Imports

###### External Data Objects

Data Objects provided by the Java Runtime environment may need to be registered to be available to rule authoring where such Data Objects are not implicitly available as part of an existing Data Object defined within the Business Central or a Project dependency. For example an Author may want to define a rule that checks for `java.util.ArrayList` in Working Memory. If a domain Data Object has a field of type `java.util.ArrayList`, then there is no need to create a registration.

###### Metadata

Metadata for the project.imports file.

##### 3.8.5.5. Duplicate GAV detection

When performing any of the following operations a check is now made against all Maven Repositories, resolved for the Project, for whether the Project’s GroupId, ArtifactId and Version pre-exist. If a clash is found the operation is prevented; although this can be overridden by Users with the `admin` role.

| The feature can be disabled by setting the System Property `org.guvnor.project.gav.check.disabled` to `true`.

Resolved repositories are those discovered in:-

- The Project’s `POM``<repositories>` section (or any parent `POM`).

- The Project’s `POM``<distributionManagement>` section.

- Maven’s global `settings.xml` configuration file.

Affected operations:-

- Creation of new Managed Repositories.

- Saving a Project definition with the Project Editor.

- Adding new Modules to a Managed Multi-Module Repository.

- Saving the `pom.xml` file.

- Build & installing a Project with the Project Editor.

- Build & deploying a Project with the Project Editor.

- Asset Management operations building, installing or deploying Projects.

- `REST` operations creating, installing or deploying Projects.

Users with the `Admin` role can override the list of Repositories checked using the "Repositories" settings in the Project Editor.

Figure 32. Project Editor - Viewing resolved Repositories
Figure 33. Project Editor - The list of resolved Repositories
Figure 34. Duplicate GAV detected

#### 3.8.6. Validation

Business Central provides a common and consistent service for users to understand whether files authored within the environment are valid.

##### 3.8.6.1. Problem Panel

The Problems Panel shows real-time validation results of assets within a Project.

When a Project is selected from the Project Explorer the Problems Panel will refresh with validation results of the chosen Project.

When files are created, saved or deleted the Problems Panel content will update to show either new validation errors, or remove existing if a file was deleted.

Figure 35. The Problems Panel

##### 3.8.6.2. On demand validation

It is not always desirable to save a file in order to determine whether it is in a valid state.

All of the file editors provide the ability to validate the content before it is saved.

Clicking on the 'Validate' button shows validation errors, if any.

#### 3.8.7. Data Modeller

##### 3.8.7.1. First steps to create a data model

By default, a data model is always constrained to the context of a project. For the purpose of this tutorial, we will assume that a correctly configured project already exists and the authoring page is open.

To start the creation of a data model inside a project, take the following steps:

1. From the home panel, select the Design page and select the given project.

   Figure 36. Go to authoring page and select a project

2. Open the Data Modeller tool by clicking on a Data Object file, or using the "Add Asset → Data Object" menu option. Set Data Object name to "PurchaseOrder" and click Ok.

   Figure 37. Click a Data Object

This will start up the Data Modeller tool, which has the following general aspect:

Figure 38. Data modeller overview

The "Editor" tab is divided into the following sections:

- The new field section is dedicated to the creation of new fields, and is opened when the "add field" button is pressed.

  Figure 39. New field creation

- The Data Object’s "field browser" section displays a list with the data object fields.

  Figure 40. The Data Object’s field browser

- The "Data Object / Field general properties" section. This is the rightmost section of the Data Modeller editor and visualizes the "Data Object" or "Field" general properties, depending on user selection.

  Data Object general properties can be selected by clicking on the Data Object Selector.

  Figure 41. Data Object selector
  Figure 42. Data Object general properties

  Field general properties can be selected by clicking on a field.

Figure 43. Field selector
Figure 44. Field general properties

- On the right side of Business Central a new "Tool Bar" is provided that enables the selection of different context sensitive tool windows that will let the user do domain specific configurations. Currently four tool windows are provided for the following domains "Drools & jBPM", "OptaPlanner", "Persistence" and "Advanced" configurations.

  Figure 45. Data modeller Tool Bar
  Figure 46. Drools & jBPM tool window
  Figure 47. OptaPlanner tool window

  | To see and use the OptaPlanner tool window, the user needs to have the role `plannermgmt`.

  Figure 48. Persistence tool window
  Figure 49. Advanced tool window

The "Source" tab shows an editor that allows the visualization and modification of the generated java code.

- Round trip between the "Editor" and "Source" tabs is possible, and also source code preservation is provided. It means that no matter where the Java code was generated (e.g. Eclipse, Data modeller), the data modeller will only update the necessary code blocks to maintain the model updated.

  Figure 50. Source editor

The "Overview" tab shows the standard metadata and version information as the other workbench editors.

##### 3.8.7.2. Data Objects

A data model consists of data objects which are a logical representation of some real-world data. Such data objects have a fixed set of modeller (or application-owned) properties, such as its internal identifier, a label, description, package etc. Besides those, a data object also has a variable set of user-defined fields, which are an abstraction of a real-world property of the type of data that this logical data object represents.

Creating a data object can be achieved using the Business Central "New Item - Data Object" menu option.

Figure 51. New Data Object menu option

Both resource name and location are mandatory parameters. When the "Ok" button is pressed a new Java file will be created and a new editor instance will be opened for the file edition. The optional "Persistable" attribute will add by default configurations on the data object in order to make it a JPA entity. Use this option if your jBPM project needs to store data object’s information in a database.

##### 3.8.7.3. Properties & relationships

Once the data object has been created, it now has to be completed by adding user-defined properties to its definition. This can be achieved by pressing the "add field" button. The "New Field" dialog will be opened and the new field can be created by pressing the "Create" button. The "Create and continue" button will also add the new field to the Data Object, but won’t close the dialog. In this way multiple fields can be created avoiding the popup opening multiple times. The following fields can (or must) be filled out:

- The field’s internal identifier (mandatory). The value of this field must be unique per data object, i.e. if the proposed identifier already exists within current data object, an error message will be displayed.

- A label (optional): as with the data object definition, the user can define a user-friendly label for the data object field which is about to be created. This has no further implications on how fields from objects of this data object will be treated. If a label is defined, then this is how the field will be displayed throughout the data modeller tool.

- A field type (mandatory): each data object field needs to be assigned with a type.

  This type can be either of the following:

  1. A 'primitive java object' type: these include most of the object equivalents of the standard Java primitive types, such as Boolean, Short, Float, etc, as well as String, Date, BigDecimal and BigInteger.

     Figure 52. Primitive object field types

  2. A 'data object' type: any user defined data object automatically becomes a candidate to be defined as a field type of another data object, thus enabling the creation of relationships between them. A data object field can be created either in 'single' or in 'multiple' form, the latter implying that the field will be defined as a collection of this type, which will be indicated by selecting "List" checkbox.

Figure 53. Data object field types

1. A 'primitive java' type: these include java primitive types byte, short, int, long, float, double, char and boolean.

Figure 54. Primitive field types

When finished introducing the initial information for a new field, clicking the 'Create' button will add the newly created field to the end of the data object’s fields table below:

Figure 55. New field has been created

The new field will also automatically be selected in the data object’s field list, and its properties will be shown in the Field general properties editor. Additionally the field properties will be loaded in the different tool windows, in this way the field will be ready for edition in whatever selected tool window.

At any time, any field (without restrictions) can be deleted from a data object definition by clicking on the corresponding 'x' icon in the data object’s fields table.

##### 3.8.7.4. Additional options

As stated before, both Data Objects as well as Fields require some of their initial properties to be set upon creation. Additionally there are three domains of properties that can be configured for a given Data Object. A domain is basically a set of properties related to a given business area. Current available domains are, "Drools & jBPM", "Persistence" and the "Advanced" domain. To work on a given domain the user should select the corresponding "Tool window" (see below) on the right side toolbar. Every tool window usually provides two editors, the "Data Object" level editor and the "Field" level editor, that will be shown depending on the last selected item, the Data Object or the Field.

###### Drools & jBPM domain

The Drools & jBPM domain editors manages the set of Data Object or Field properties related to drools applications.

Drools & jBPM object editor

The Drools & jBPM object editor manages the object level drools properties

Figure 56. The data object’s properties

- TypeSafe: this property allows to enable/disable the type safe behaviour for current type. By default all type declarations are compiled with type safety enabled. (See Drools for more information on this matter).

- ClassReactive: this property allows to mark this type to be treated as "Class Reactive" by the Drools engine. (See Drools for more information on this matter).

- PropertyReactive: this property allows to mark this type to be treated as "Property Reactive" by the Drools engine. (See Drools for more information on this matter).

- Role: this property allows to configure how the Drools engine should handle instances of this type: either as regular facts or as events. By default all types are handled as a regular fact, so for the time being the only value that can be set is "Event" to declare that this type should be handled as an event. (See Drools Fusion for more information on this matter).

- Timestamp: this property allows to configure the "timestamp" for an event, by selecting one of his attributes. If set the Drools engine will use the timestamp from the given attribute instead of reading it from the Session Clock. If not, the Drools engine will automatically assign a timestamp to the event. (See Drools Fusion for more information on this matter).

- Duration: this property allows to configure the "duration" for an event, by selecting one of his attributes. If set the Drools engine will use the duration from the given attribute instead of using the default event duration = 0. (See Drools Fusion for more information on this matter).

- Expires: this property allows to configure the "time offset" for an event expiration. If set, this value must be a temporal interval in the form: [d][#h][#m][#s][[ms]] Where [ ] means an optional parameter and # means a numeric value. e.g.: 1d2h, means one day and two hours. (See Drools Fusion for more information on this matter).

- Remotable: If checked this property makes the Data Object available to be used with jBPM remote services as REST, JMS and WS. (See jBPM for more information on this matter).

Drools & jBPM field editor

The Drools & jBPM object editor manages the field level drools properties

Figure 57. The data object’s field properties

- Equals: checking this property for a Data Object field implies that it will be taken into account, at the code generation level, for the creation of both the equals() and hashCode() methods in the generated Java class. We will explain this in more detail in the following section.

- Position: this field requires a zero or positive integer. When set, this field will be interpreted by the Drools engine as a positional argument (see the section below and also the Drools documentation for more information on this subject).

###### Persistence domain

The Persistence domain editors manages the set of Data Object or Field properties related to persistence.

Persistence domain object editor

Persistence domain object editor manages the object level persistence properties

Figure 58. The data object’s properties

- Persistable: this property allows to configure current Data Object as persistable.

- Table name: this property allows to set a user defined database table name for current Data Object.

Persistence domain field editor

The persistence domain field editor manages the field level persistence properties and is divided into three sections.

Figure 59. Persistence domain field editor sections
Identifier:

A persistable Data Object should have one and only one field defined as the Data Object identifier. The identifier is typically a unique number that distinguishes a given Data Object instance from all other instances of the same class.

- Is Identifier: marks current field as the Data Object identifier. A persistable Data Object should have one and only one field marked as identifier, and it should be a base java type, like String, Integer, Long, etc. A field that references a Data Object, or is a multiple field can not be marked as identifier. And also composite identifiers are not supported in this version. When a persistable Data Object is created an identifier field is created by default with the properly initializations, it’s strongly recommended to use this identifier.

- Generation Strategy: the generation strategy establishes how the identifier values will be automatically generated when the Data Object instances are created and stored in a database. (e.g. by the forms associated to jBPM processes human tasks.) When the by default Identifier field is created, the generation strategy will be also automatically set and it’s strongly recommended to use this configuration.

- Sequence Generator: the generator represents the seed for the values that will be used by the Generation Strategy. When the by default Identifier field is created the Sequence Generator will be also automatically generated and properly configured to be used by the Generation Strategy.

Column Properties:

The column properties section enables the customization of some properties of the database column that will store the field value.

- Column name: optional value that sets the database column name for the given field.

- Unique: When checked the unique property establishes that current field value should be a unique key when stored in the database. (if not set the default value is false)

- Nullable: When checked establishes that current field value can be null when stored in a database. (if not set the default value is true)

- Insertable: When checked establishes that column will be included in SQL INSERT statements generated by the persistence provider. (if not set the default value is true)

- Updatable: When checked establishes that the column will be included SQL UPDATE statements generated by the persistence provider. (if not set the default value is true)

Relationship Properties:

When the field’s type is a Data Object type, or a list of a Data Object type a relationship type should be set in order to let the persistence provider to manage the relation. Fortunately this relation type is automatically set when such kind of fields are added to an already marked as persistable Data Object. The relationship type is set by the following popup.

Figure 60. Relationship configuration popup

- Relationship type: sets the type of relation from one of the following options:

  One to one: typically used for 1:1 relations where "A is related to one instance of B", and B exists only when A exists. e.g. PurchaseOrder → PurchaseOrderHeader (a PurchaseOrderHeader exists only if the PurchaseOrder exists)

  One to many: typically used for 1:N relations where "A is related to N instances of B", and the related instances of B exists only when A exists. e.g. PurchaseOrder → PurchaseOrderLine (a PurchaseOrderLine exists only if the PurchaseOrder exists)

  Many to one: typically used for 1:1 relations where "A is related to one instance of B", and B can exist even without A. e.g. PurchaseOrder → Client (a Client can exist in the database even without an associated PurchaseOrder)

  Many to many: typically used for N:N relations where "A can be related to N instances of B, and B can be related to M instances of A at the same time", and both B and A instances can exist in the database independently of the related instances. e.g. Course → Student. (Course can be related to N Students, and a given Student can attend to M courses)

  When a field of type "Data Object" is added to a given persistable Data Object, the "Many to One" relationship type is generated by default.

  And when a field of type "list of Data Object" is added to a given persistable Data Object , the "One to Many" relationship is generated by default.

- Cascade mode: Defines the set of cascadable operations that are propagated to the associated entity. The value cascade=ALL is equivalent to cascade={PERSIST, MERGE, REMOVE, REFRESH}. e.g. when A → B, and cascade "PERSIST or ALL" is set, if A is saved, then B will also be saved.

  The by default cascade mode created by the data modeller is "ALL" and it’s strongly recommended to use this mode when Data Objects are being used by jBPM processes and forms.

- Fetch mode: Defines how related data will be fetched from database at reading time.

  EAGER: related data will be read at the same time. e.g. If A → B, when A is read from database B will be read at the same time.

  LAZY: reading of related data will be delayed usually to the moment they are required. e.g. If PurchaseOrder → PurchaseOrderLine the lines reading will be postponed until a method "getLines()" is invoked on a PurchaseOrder instance.

  The default fetch mode created by the data modeller is "EAGER" and it’s strongly recommended to use this mode when Data Objects are being used by jBPM processes and forms.

- Optional: establishes if the right side member of a relationship can be null.

- Mapped by: used for reverse relations.

###### Advanced domain

The advanced domain enables the configuration of whatever parameter set by the other domains as well as the adding of arbitrary parameters. As it will be shown in the code generation section every "Data Object / Field" parameter is represented by a java annotation. The advanced mode enables the configuration of this annotations.

Advanced domain Data Object / Field editor.

The advanced domain editor has the same shape for both Data Object and Field.

Figure 61. Advanced domain editor.

The following operations are available

- delete: enables the deletion of a given Data Object or Field annotation.

- clear: clears a given annotation parameter value.

- edit: enables the edition of a given annotation parameter value.

- add annotation: The add annotation button will start a wizard that will let the addition of whatever java annotation available in the project dependencies.

  Add annotation wizard step #1: the first step of the wizard requires the entering of a fully qualified class name of an annotation, and by pressing the "search" button the annotation definition will be loaded into the wizard. Additionally when the annotation definition is loaded, different wizard steps will be created in order to enable the completion of the different annotation parameters. Required parameters will be marked with "*".

  Figure 62. Annotation definition loaded into the wizard.

  Whenever it’s possible the wizard will provide a suitable editor for the given parameters.

  Figure 63. Automatically generated enum values editor for an Enumeration annotation parameter.

  A generic parameter editor will be provided when it’s not possible to calculate a customized editor

  Figure 64. Generic annotation parameter editor

  When all required parameters have been entered and validated, the finish button will be enabled and the wizard can be completed by adding an annotation to the given Data Object or Field.

##### 3.8.7.5. Generate data model code.

The data model in itself is merely a visual tool that allows the user to define high-level data structures, for them to interact with the Drools engine on the one hand, and the jBPM platform on the other. In order for this to become possible, these high-level visual structures have to be transformed into low-level artifacts that can effectively be consumed by these platforms. These artifacts are Java POJOs (Plain Old Java Objects), and they are generated every time the data model is saved, by pressing the "Save" button in the top Data Modeller Menu. Additionally when the user round trip between the "Editor" and "Source" tab, the code is auto generated to maintain the consistency with the Editor view and vice versa.

Figure 65. Save the data model from the top menu

The resulting code is generated according to the following transformation rules:

- The data object’s identifier property will become the Java class’s name. It therefore needs to be a valid Java identifier.

- The data object’s package property becomes the Java class’s package declaration.

- The data object’s superclass property (if present) becomes the Java class’s extension declaration.

- The data object’s label and description properties will translate into the Java annotations "@org.kie.api.definition.type.Label" and "@org.kie.api.definition.type.Description", respectively. These annotations are merely a way of preserving the associated information, and as yet are not processed any further.

- The data object’s role property (if present) will be translated into the "@org.kie.api.definition.type.Role" Java annotation, that IS interpreted by the application platform, in the sense that it marks this Java class as a Drools Event Fact-Type.

- The data object’s type safe property (if present) will be translated into the "@org.kie.api.definition.type.TypeSafe Java annotation. (see Drools)

- The data object’s class reactive property (if present) will be translated into the "@org.kie.api.definition.type.ClassReactive Java annotation. (see Drools)

- The data object’s property reactive property (if present) will be translated into the "@org.kie.api.definition.type.PropertyReactive Java annotation. (see Drools)

- The data object’s timestamp property (if present) will be translated into the "@org.kie.api.definition.type.Timestamp Java annotation. (see Drools)

- The data object’s duration property (if present) will be translated into the "@org.kie.api.definition.type.Duration Java annotation. (see Drools)

- The data object’s expires property (if present) will be translated into the "@org.kie.api.definition.type.Expires Java annotation. (see Drools)

- The data object’s remotable property (if present) will be translated into the "@org.kie.api.remote.Remotable Java annotation. (see jBPM)

A standard Java default (or no parameter) constructor is generated, as well as a full parameter constructor, i.e. a constructor that accepts as parameters a value for each of the data object’s user-defined fields.

The data object’s user-defined fields are translated into Java class fields, each one of them with its own getter and setter method, according to the following transformation rules:

- The data object field’s identifier will become the Java field identifier. It therefore needs to be a valid Java identifier.

- The data object field’s type is directly translated into the Java class’s field type. In case the field was declared to be multiple (i.e. 'List'), then the generated field is of the "java.util.List" type.

- The equals property: when it is set for a specific field, then this class property will be annotated with the "@org.kie.api.definition.type.Key" annotation, which is interpreted by the Drools engine, and it will 'participate' in the generated equals() method, which overwrites the equals() method of the Object class. The latter implies that if the field is a 'primitive' type, the equals method will simply compares its value with the value of the corresponding field in another instance of the class. If the field is a sub-entity or a collection type, then the equals method will make a method-call to the equals method of the corresponding data object’s Java class, or of the java.util.List standard Java class, respectively.

  If the equals property is checked for ANY of the data object’s user defined fields, then this also implies that in addition to the default generated constructors another constructor is generated, accepting as parameters all of the fields that were marked with Equals. Furthermore, generation of the equals() method also implies that also the Object class’s hashCode() method is overwritten, in such a manner that it will call the hashCode() methods of the corresponding Java class types (be it 'primitive' or user-defined types) for all the fields that were marked with Equals in the Data Model.

- The position property: this field property is automatically set for all user-defined fields, starting from 0, and incrementing by 1 for each subsequent new field. However the user can freely change the position among the fields. At code generation time this property is translated into the "@org.kie.api.definition.type.Position" annotation, which can be interpreted by the Drools engine. Also, the established property order determines the order of the constructor parameters in the generated Java class.

As an example, the generated Java class code for the Purchase Order data object, corresponding to its definition as shown in the following figure purchase_example.jpg is visualized in the figure at the bottom of this chapter. Note that the two of the data object’s fields, namely 'header' and 'lines' were marked with Equals, and have been assigned with the positions 2 and 1, respectively).

Figure 66. Purchase Order configuration

        package org.jbpm.examples.purchases;

        /**
        * This class was automatically generated by the data modeler tool.
        */
        @org.kie.api.definition.type.Label("Purchase Order")
        @org.kie.api.definition.type.TypeSafe(true)
        @org.kie.api.definition.type.Role(org.kie.api.definition.type.Role.Type.EVENT)
        @org.kie.api.definition.type.Expires("2d")
        @org.kie.api.remote.Remotable
        public class PurchaseOrder implements java.io.Serializable
        {

        static final long serialVersionUID = 1L;

        @org.kie.api.definition.type.Label("Total")
        @org.kie.api.definition.type.Position(3)
        private java.lang.Double total;

        @org.kie.api.definition.type.Label("Description")
        @org.kie.api.definition.type.Position(0)
        private java.lang.String description;

        @org.kie.api.definition.type.Label("Lines")
        @org.kie.api.definition.type.Position(2)
        @org.kie.api.definition.type.Key
        private java.util.List<org.jbpm.examples.purchases.PurchaseOrderLine> lines;

        @org.kie.api.definition.type.Label("Header")
        @org.kie.api.definition.type.Position(1)
        @org.kie.api.definition.type.Key
        private org.jbpm.examples.purchases.PurchaseOrderHeader header;

        @org.kie.api.definition.type.Position(4)
        private java.lang.Boolean requiresCFOApproval;

        public PurchaseOrder()
        {
        }

        public java.lang.Double getTotal()
        {
        return this.total;
        }

        public void setTotal(java.lang.Double total)
        {
        this.total = total;
        }

        public java.lang.String getDescription()
        {
        return this.description;
        }

        public void setDescription(java.lang.String description)
        {
        this.description = description;
        }

        public java.util.List<org.jbpm.examples.purchases.PurchaseOrderLine> getLines()
        {
        return this.lines;
        }

        public void setLines(java.util.List<org.jbpm.examples.purchases.PurchaseOrderLine> lines)
        {
        this.lines = lines;
        }

        public org.jbpm.examples.purchases.PurchaseOrderHeader getHeader()
        {
        return this.header;
        }

        public void setHeader(org.jbpm.examples.purchases.PurchaseOrderHeader header)
        {
        this.header = header;
        }

        public java.lang.Boolean getRequiresCFOApproval()
        {
        return this.requiresCFOApproval;
        }

        public void setRequiresCFOApproval(java.lang.Boolean requiresCFOApproval)
        {
        this.requiresCFOApproval = requiresCFOApproval;
        }

        public PurchaseOrder(java.lang.Double total, java.lang.String description,
        java.util.List<org.jbpm.examples.purchases.PurchaseOrderLine> lines,
        org.jbpm.examples.purchases.PurchaseOrderHeader header,
        java.lang.Boolean requiresCFOApproval)
        {
        this.total = total;
        this.description = description;
        this.lines = lines;
        this.header = header;
        this.requiresCFOApproval = requiresCFOApproval;
        }

        public PurchaseOrder(java.lang.String description,
        org.jbpm.examples.purchases.PurchaseOrderHeader header,
        java.util.List<org.jbpm.examples.purchases.PurchaseOrderLine> lines,
        java.lang.Double total, java.lang.Boolean requiresCFOApproval)
        {
        this.description = description;
        this.header = header;
        this.lines = lines;
        this.total = total;
        this.requiresCFOApproval = requiresCFOApproval;
        }

        public PurchaseOrder(
        java.util.List<org.jbpm.examples.purchases.PurchaseOrderLine> lines,
        org.jbpm.examples.purchases.PurchaseOrderHeader header)
        {
        this.lines = lines;
        this.header = header;
        }

        @Override
        public boolean equals(Object o)
        {
        if (this == o)
        return true;
        if (o == null || getClass() != o.getClass())
        return false;
        org.jbpm.examples.purchases.PurchaseOrder that = (org.jbpm.examples.purchases.PurchaseOrder) o;
        if (lines != null ? !lines.equals(that.lines) : that.lines != null)
        return false;
        if (header != null ? !header.equals(that.header) : that.header != null)
        return false;
        return true;
        }

        @Override
        public int hashCode()
        {
        int result = 17;
        result = 31 * result + (lines != null ? lines.hashCode() : 0);
        result = 31 * result + (header != null ? header.hashCode() : 0);
        return result;
        }

        }

##### 3.8.7.6. Using external models

Using an external model means the ability to use a set for already defined POJOs in current project context. In order to make those POJOs available a dependency to the given JAR should be added. Once the dependency has been added the external POJOs can be referenced from current project data model.

There are two ways to add a dependency to an external JAR file:

- Dependency to a JAR file already installed in current local M2 repository (typically associated the user home).

- Dependency to a JAR file installed in current Business Central "Guvnor M2 repository". (internal to the application)

###### Dependency to a JAR file in local M2 repository

To add a dependency to a JAR file in local M2 repository, follow these steps.

Open the Project Editor for current project and select the Dependencies view.
Figure 67. Project editor.
Click the "Add" button to add a new dependency line.
Figure 68. New dependency line.
Complete the GAV for the JAR file already installed in local M2 repository.
Figure 69. Dependency line edition.
Save the project to update its dependencies.

When project is saved the POJOs defined in the external file will be available.

Figure 70. Save project.

###### Dependency to a JAR file in current "Guvnor M2 repository".

To add a dependency to a JAR file in current "Guvnor M2 repository", follow these steps.

Open the Maven Artifact Repository editor.
Figure 71. Guvnor M2 Repository editor.
Browse your local file system and select the JAR file to be uploaded using the Browse button.
Figure 72. File browser.
Upload the file using the Upload button.
Figure 73. File upload success.
Guvnor M2 repository files.

Once the file has been loaded it will be displayed in the repository files list.

Figure 74. Files list.
Provide a GAV for the uploaded file (optional).

If the uploaded file is not a valid Maven JAR (don’t have a pom.xml file) the system will prompt the user in order to provide a GAV for the file to be installed.

Figure 75. Not valid POM.
Figure 76. Enter GAV manually.
Add dependency from repository.

Open the project editor (see below) and click the "Add from repository" button to open the JAR selector to see all the installed JAR files in current "Guvnor M2 repository". When the desired file is selected the project should be saved in order to make the new dependency available.

Figure 77. Select JAR from "Maven Artifact Repository".

###### Using the external objects

When a dependency to an external JAR has been set, the external POJOs can be used in the context of current project data model in the following ways:

- External POJOs can be extended by current model data objects.

- External POJOs can be used as field types for current model data objects.

The following screenshot shows how external objects are prefixed with the string " -ext- " in order to be quickly identified.

Figure 78. Identifying external objects.

##### 3.8.7.7. Roundtrip and concurrency

Current version implements roundtrip and code preservation between Data modeller and Java source code. No matter where the Java code was generated (e.g. Eclipse, Data modeller), the data modeller will only create/delete/update the necessary code elements to maintain the model updated, i.e, fields, getter/setters, constructors, equals method and hashCode method. Also whatever Type or Field annotation not managed by the Data Modeler will be preserved when the Java sources are updated by the Data modeller.

Aside from code preservation, like in the other Business Central editors, concurrent modification scenarios are still possible. Common scenarios are when two different users are updating the model for the same project, e.g. using the data modeller or executing a 'git push command' that modifies project sources.

From an application context’s perspective, we can basically identify two different main scenarios:

###### No changes have been undertaken through the application

In this scenario the application user has basically just been navigating through the data model, without making any changes to it. Meanwhile, another user modifies the data model externally.

In this case, no immediate warning is issued to the application user. However, as soon as the user tries to make any kind of change, such as add or remove data objects or properties, or change any of the existing ones, the following pop-up will be shown:

Figure 79. External changes warning

The user can choose to either:

- Re-open the data model, thus loading any external changes, and then perform the modification he was about to undertake, or

- Ignore any external changes, and go ahead with the modification to the model. In this case, when trying to persist these changes, another pop-up warning will be shown:

  Figure 80. Force save / re-open

  The "Force Save" option will effectively overwrite any external changes, while "Re-open" will discard any local changes and reload the model.

  | "Force Save" overwrites any external changes!

###### Changes have been undertaken through the application

The application user has made changes to the data model. Meanwhile, another user simultaneously modifies the data model from outside the application context.

In this alternative scenario, immediately after the external user commits his changes to the asset repository (or e.g. saves the model with the data modeller in a different session), a warning is issued to the application user:

Figure 81. External changes warning

As with the previous scenario, the user can choose to either:

- Re-open the data model, thus losing any modifications that were made through the application, or

- Ignore any external changes, and continue working on the model.

  One of the following possibilities can now occur: ** The user tries to persist the changes he made to the model by clicking the "Save" button in the data modeller top level menu. This leads to the following warning message:

  +

  Figure 82. Force save / re-open

  The "Force Save" option will effectively overwrite any external changes, while "Re-open" will discard any local changes and reload the model.

#### 3.8.8. Data sets authoring

A data set is a collection of related sets of information and can be stored in a database, in a Microsoft Excel file, or in memory. A data set definition instructs Business Central methods to access, read, and parse a data set. Business Central does not store data. It enables you to define access to a data set regardless of where the data is stored.

For example, if data is stored in a database, a valid data set can contain the entire database or a subset of the database as a result of an SQL query. In both cases the data is used as input for the reporting components of Business Central which then displays the information.

To access a data set, you must create and register a data set definition. The data set definition specifies the location of the data set, options to access it, read it, and parse it, and the columns that it contains.

| The Data Sets page is visible only to users with the admin role.

##### 3.8.8.1. Adding data sets

You can create a data set to fetch data from an external data source and use that data for the reporting components.

Procedure

1. In Business Central, go to Admin → Data Sets.

   The Data Sets page opens.

2. Click New Data Set and select one of the following provider types:

   - Bean: Generates a data set from a Java class

   - CSV: Generates a data set from a remote or local CSV file

   - SQL: Generates a data set from an ANSI-SQL compliant database

   - Elastic Search: Generates a data set from Elastic Search nodes

   - Prometheus: Generates a data set using the Prometheus query

   - Kafka: Generates a data set using metrics from Kafka broker, consumer, or producer

     | You must configure KIE Server for Prometheus, Kafka, and Execution Server options.

3. Complete the Data Set Creation Wizard and click Test.

   | The configuration steps differ based on the provider you choose.

4. Click Save.

##### 3.8.8.2. Editing data sets

You can edit existing data sets to ensure that the data fetched to the reporting components is up-to-date.

Procedure

1. In Business Central, go to Admin → Data Sets.

   The Data Set Explorer page opens.

2. In the Data Set Explorer pane, search for the data set you want to edit, select the data set, and click Edit.

3. In the Data Set Editor pane, use the appropriate tab to edit the data as required. The tabs differ based on the data set provider type you chose.

   For example, the following changes are applicable for editing a CSV data provider:

   - CSV Configuration: Enables you to change the name of the data set definition, the source file, the separator, and other properties.

   - Preview: Enables you to preview the data. After you click Test in the CSV Configuration tab, the system executes the data set lookup call and if the data is available, a preview appears. Note that the Preview tab has two sub-tabs:

     - Data columns: Enables you to specify what columns are part of your data set definition.

     - Filter: Enables you to add a new filter.

   - Advanced: Enables you to manage the following configurations:

     - Caching: See Caching data for more information.

     - Cache life-cycle Enables you to specify an interval of time after which a data set (or data) is refreshed. The Refresh on stale data feature refreshes the cached data when the back-end data changes.

4. After making the required changes, click Validate.

5. Click Save.

##### 3.8.8.3. Data refresh

The data refresh feature enables you to specify an interval of time after which a data set (or data) is refreshed. You can access the Data refresh every feature on the Advanced tab of the data set. The Refresh on stale data feature refreshes the cached data when the back-end data changes.

##### 3.8.8.4. Caching data

Business Central provides caching mechanisms for storing data sets and performing data operations using in-memory data. Caching data reduces network traffic, remote system payload, and processing time. To avoid performance issues, configure the cache settings in Business Central.

For any data lookup call that results in a data set, the caching method determines where the data lookup call is executed and where the resulting data set is stored. An example of a data lookup call would be all the mortgage applications whose locale parameter is set as "Urban".

Business Central data set functionality provides two cache levels:

- Client level

- Back-end level

You can set the Client Cache and Backend Cache settings on the Advanced tab of the data set.

###### Client cache

When the cache is turned on, the data set is cached in a web browser during the lookup operation and further lookup operations do not perform requests to the back-end. Data set operations like grouping, aggregations, filtering, and sorting are processed in the web browser. Enable client caching only if the data set size is small, for example, for data sets with less than 10 MB of data. For large data sets, browser issues such as slow performance or intermittent freezing can occur. Client caching reduces the number of back-end requests including requests to the storage system.

###### Back-end cache

When the cache is enabled, the Drools engine caches the data set. This reduces the number of back-end requests to the remote storage system. All data set operations are performed in the Drools engine using in-memory data. Enable back-end caching only if the data set size is not updated frequently and it can be stored and processed in memory. Using back-end caching is also useful in cases with low latency connectivity issues with the remote storage.

| Back-end cache settings are not always visible in the Advanced tab of the Data Set Editor because Java and CSV data providers rely on back-end caching (data set must be in the memory) in order to resolve any data lookup operation using the in-memory Drools engine.

#### 3.8.9. Data source and database driver management

Business Central provides data source management features that enable you to define data sources for accessing a database. These data sources are then used by other Business Central components such as data sets. A database driver enables communication between a data source and the targeted database.

From the Data Source Authoring page you can add data sources and database drivers to Business Central.

| Business Central provides a default data source that can be used but cannot be edited or deleted.

##### 3.8.9.1. Adding a data source

You can add a new data source to Business Central from the Data Sources Authoring page.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Data Sources.

2. In the DataSource Explorer pane, click Add DataSource.

   The New data source window opens.

3. In the New data source window, enter the Name, Connection URL, User, Password, and Driver fields of the data source.

4. Click Test Connection to verify the connection to the database.

5. Click Finish.

##### 3.8.9.2. Editing a data source

You can edit the properties of a data source and also test its connection to the database in Business Central.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Data Sources.

2. In the DataSource Explorer pane, click the data source you want to edit.

3. In the Data Source Definition pane, make the necessary changes to the Name, Connection URL, User, Password, and the Driver fields.

4. Click Test Connection to verify the connection to the database.

5. Click Update.

6. Click Save.

##### 3.8.9.3. Deleting a data source

You can delete an existing data source from the DataSource Explorer pane in Business Central.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Data Sources.

2. In the DataSource Explorer pane, click the data source you want to delete.

3. Click Remove.

4. Click Delete to confirm the deletion of the data source.

##### 3.8.9.4. Adding a database driver

You can add a new database driver to Business Central.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Data Sources.

2. In the DataSource Explorer pane, click Add Driver.

   The New driver window opens.

3. In the New driver window, enter the Name, Driver Class Name, Group Id, Artifact Id, and Version fields of the database driver.

4. Click Finish.

##### 3.8.9.5. Editing a database driver

You can edit the properties of a database driver from the Driver Definition pane.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Data Sources.

2. In the DataSource Explorer pane, select the driver you want to edit.

3. In the Driver Definition pane, make the necessary changes to the Name, Driver Class Name, Group Id, Artifact Id, and the Version fields.

4. Click Update.

5. Click Yes.

##### 3.8.9.6. Deleting a database driver

You can remove database drivers from the Data Source Definition pane of Business Central.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Data Sources.

2. In the DataSource Explorer pane, select the driver you want to delete.

3. Click Remove.

4. Click Delete.

### 3.9. User and group management

Business Central defines three types of entities for security management: users, groups, and roles. You can assign permissions to both roles and groups. You can assign the following roles in Business Central:

- process-admin

- manager

- admin

- analyst

- rest-all

- developer

- rest-project

- user

| User roles in the application Role Registry have a role identifier, whereas user groups do not.

Use Business Central to create and manage as many users and groups as you require. A user must be assigned to at least one user-specific role to log in to Business Central. User privileges depend on permissions from the groups and roles that the user is a member of. Note that the role or group priority is considered if a user has several roles or groups assigned to it.

#### 3.9.1. Creating users

User privileges and settings are controlled by the roles assigned to a user and the groups that a user belongs to. You can create any number of users in Business Central.

| Do not create a user called `unknown` in jBPM engine or KIE Server. The `unknown` user account is a reserved system name with superuser access. The `unknown` user account performs tasks related to the SLA violation listener when there are no users logged in.

Procedure

1. In Business Central, select the Admin icon in the top-right corner of the screen and select Users.

2. Click New user, enter a user name, and then click Next.

3. To assign roles to the user, click the Roles tab, click Add Roles, select the desired roles, and click Add to selected roles.

4. Optional: To assign groups to the user, click the Groups tab, click Add to groups, select the desired groups, and click Add to selected groups.

5. Click Create.

6. Click Yes to set a password for the user, enter a desired password, and click Change.

| The user must have at least one role to access Business Central.

#### 3.9.2. Editing users

You can change the group and role of a user using the Users option on the Business Central Settings page. All user permissions are based on the group and role permissions of the user. You can view the user permissions from the Permissions tab.

Procedure

1. In Business Central, select the Admin icon in the top-right corner of the screen and select Users.

2. From the All users list, click the user you want to edit. The user details display in the right pane.

3. Click Edit to perform any of the following tasks:

   - To change the groups of a user, click the Groups tab, click Add to groups, select the groups you want the user to be part of, click Add to selected groups, and click Save.

   - To change the roles of a user, click the Roles tab, click Add roles, select the roles you want to assign to the user, click Add to selected roles, and click Save.

   - To view the user permissions, click the Permissions tab and expand the attributes.

   - To change the password, click Change Password, enter the new password, and click Change.

   - To delete the user, click Delete and then click Yes to confirm removal.

#### 3.9.3. Creating groups

In Business Central, you can use groups to control permissions for a collection of users. You can create as many groups as you want but a group must have at least one user.

Procedure

1. In Business Central, select the Admin icon in the top-right corner of the screen and select Groups.

2. Click New group, enter a group name, and then click Next.

3. Select the users that you want to add to this group, and then click Add selected users.

   The newly created group is listed under All groups.

#### 3.9.4. Editing groups

You can edit the attribute of a group such as home page, priority, and permissions according to your requirements. From the Groups option on the Business Central Settings page, you can modify or delete a group.

Procedure

1. In Business Central, select the Admin icon in the top-right corner of the screen and select Groups.

2. From the All groups list, click the group that you want to edit. The user details display in the right pane.

3. Select the home page from the Home Page list.

4. Select the priority from the Priority list.

5. In the Permissions section, expand the resource attribute and change its permission.

   | You can add exceptions to Pages, Editor, Spaces, and Projects permissions.

6. Click Save to apply the changes.

### 3.10. Security management

Security management is the process of managing users, groups, and permissions. You can control access to Business Central resources and features from the Business Central Security management page.

Business Central defines three types of entities for security management: users, groups, and roles. You can assign permissions to both roles and groups. A user inherits permissions from the groups and roles that the user is a member of.

#### 3.10.1. Security management providers

In the context of security management, a realm restricts access to different application resources. Realms contain information about users, groups, roles, and permissions. A concrete user and group management service implementation for a specific realm is called a security management provider.

If the built-in security management providers do not meet the requirements of your application security realm, then you can build and register your own security management provider.

| If the security management provider is not installed, the user interface for managing the security realm is not available. After you install and configure a security management provider, the user and group management features are automatically enabled in the security management user interface.

Business Central includes the Red Hat JBoss EAP security management provider which supports realm types based on the contents of the `application-users.properties` or `application-roles.properties` property file.

##### 3.10.1.1. Configuring the Red Hat JBoss EAP security management provider based on property files

You can build and register your own Red Hat JBoss EAP security management provider. To use the Red Hat JBoss EAP security management provider based on property files, complete the steps in this procedure.

Prerequisites

- Red Hat JBoss EAP is installed.

Procedure

1. To use an existing users or roles property file from the Red Hat JBoss EAP instance, include the following system properties in the `EAP_HOME/standalone/configuration/application-users.properties` and `EAP_HOME/standalone/configuration/application-roles.properties` files, as shown in the following example:

       <property name="org.uberfire.ext.security.management.wildfly.properties.realm" value="ApplicationRealm"/>
       <property name="org.uberfire.ext.security.management.wildfly.properties.users-file-path" value="/standalone/configuration/application-users.properties"/>
       <property name="org.uberfire.ext.security.management.wildfly.properties.groups-file-path" value="/standalone/configuration/application-roles.properties"/>

   The following table provides a description and default value for these properties:

   Table 1. Red Hat JBoss EAP security management provider based on property files
   Property | Description | Default value
   --- | --- | ---
   `org.uberfire.ext.security.management.wildfly.properties.realm` | The name of the realm. This property is not mandatory. | `ApplicationRealm`
   `org.uberfire.ext.security.management.wildfly.properties.users-file-path` | The absolute file path for the users property file. This property is mandatory. | `./standalone/configuration/application-users.properties`
   `org.uberfire.ext.security.management.wildfly.properties.groups-file-path` | The absolute file path for the groups property file. This property is mandatory. | `./standalone/configuration/application-roles.properties`

2. Create the `security-management.properties` file in the root directory of your application. For example, create the following file:

       src/main/resources/security-management.properties

3. Enter the following system property and security provider name as a value in the `security-management.properties` file:

       <property name="org.uberfire.ext.security.management.api.userManagementServices" value="WildflyUserManagementService"/>

##### 3.10.1.2. Configuring the Red Hat JBoss EAP security management provider based on property files and CLI mode

To use the Red Hat JBoss EAP security management provider based on property files and CLI mode, complete the steps in this procedure.

Prerequisites

- Red Hat JBoss EAP is installed.

Procedure

1. To use an existing users or roles property file from the Red Hat JBoss EAP instance, include the following system properties in the `EAP_HOME/standalone/configuration/application-users.properties` and `EAP_HOME/standalone/configuration/application-roles.properties` files, as shown in the following example:

       <property name="org.uberfire.ext.security.management.wildfly.cli.host" value="localhost"/>
       <property name="org.uberfire.ext.security.management.wildfly.cli.port" value="9990"/>
       <property name="org.uberfire.ext.security.management.wildfly.cli.user" value="<USERNAME>"/>
       <property name="org.uberfire.ext.security.management.wildfly.cli.password" value="<USER_PWD>"/>
       <property name="org.uberfire.ext.security.management.wildfly.cli.realm" value="ApplicationRealm"/>

   The following table provides a description and default value for these properties:

   Table 2. Red Hat JBoss EAP security management provider based on property files and CLI mode
   Property | Description | Default value
   --- | --- | ---
   `org.uberfire.ext.security.management.wildfly.cli.host` | The native administration interface host. | `localhost`
   `org.uberfire.ext.security.management.wildfly.cli.port` | The native administration interface port. | `9990`
   `org.uberfire.ext.security.management.wildfly.cli.user` | The native administration interface username. | NA
   `org.uberfire.ext.security.management.wildfly.cli.password` | The native administration interface user’s password. | NA
   `org.uberfire.ext.security.management.wildfly.cli.realm` | The realm used by the application’s security context. | `ApplicationRealm`

2. Create the `security-management.properties` file in the root directory of your application. For example, create the following file:

       src/main/resources/security-management.properties

3. Enter the following system property and security provider name as a value in the `security-management.properties` file:

       <property name="org.uberfire.ext.security.management.api.userManagementServices" value="WildflyCLIUserManagementService"/>

#### 3.10.2. Permissions and settings

A permission is an authorization granted to a user to perform actions related to a specific resource within the application. For example, a user can have following permissions:

- View a page.

- Save the project.

- View a repository.

- Delete a dashboard.

You can grant or deny a permission and a permission can be global or resource specific. You can use permissions to protect access to resources and customize features within the application.

##### 3.10.2.1. Changing permissions for groups and roles in Business Central

In Business Central, you cannot change permissions for an individual user. However, you can change permissions for groups and roles. The changed permissions apply to users with the role or that belong to a group that you changed.

| Any changes that you make to roles or groups affect all of the users associated with that role or group.

Prerequisites

- You are logged in to Business Central with the `admin` user role.

Procedure

1. To access the Security management page in Business Central, select the Admin icon in the top-right corner of the screen.

2. Click Roles, Groups, or Users on the Business Central Settings page.

   The Security management page opens on the tab for the icon that you clicked.

3. From the list, click the role or group you want to edit. All details are displayed in the right panel.

4. Set the Home Page or Priority under the Settings section.

5. Set the Business Central, page, editor, space, and project permissions under the Permissions section.

   Figure 83. Setting the permissions

6. Click the arrow next to a resource type to expand the resource type whose permissions you want to change.

7. Optional: To add an exception for a resource type, click Add Exception and then set the permissions as required.

   | You cannot add an exception to the Business Central resource type.

8. Click Save.

##### 3.10.2.2. Changing the Business Central home page

The home page is the page that appears after you log in to Business Central. By default, the home page is set to `Home`. You can specify a different home page for each role and group.

Procedure

1. In Business Central, select the Admin icon in the top-right corner of the screen and select Roles or Groups.

2. Select a role or group.

3. Select a page from the Home Page list.

4. Click Save.

   | The role or group must have read access to a page before you can make it the home page.

##### 3.10.2.3. Setting priorities

A user can have multiple roles and belong to multiple groups. The Priority setting determines the order of precedence of a role or group.

Prerequisites

- You are logged in to Business Central with the `admin` user role.

Procedure

1. In Business Central, select the Admin icon in the top-right corner of the screen and select Roles or Groups.

2. Select a role or group.

3. Select a priority from the Priority menu, and then click Save.

| If a user has a role or belongs to a group that has conflicting settings, the settings of the role or group with the highest priority applies.

### 3.11. Artifact management

You can manage artifacts from the Artifacts page in Business Central. The artifact repository is a local Maven repository and there is only one Maven repository for each installation. Business Central recommends using Maven repository solutions like Sonatype Nexus™, Apache Archiva™, or JFrog Artifactory™.

The Artifacts page lists all the artifacts in the Maven repository. You can upload artifacts to the Maven repository.

| You can only upload JAR, KJAR, and `pom.xml` files to the Artifacts repository.

#### 3.11.1. Viewing an artifact

You can view all the content of the local maven repository from the Artifacts page.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Artifacts.

2. Click Open to view the artifact details.

3. Click Ok to go back to the Artifacts page.

#### 3.11.2. Downloading an artifact

You can download and save an artifact from Business Central repository to the local storage of a project.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Artifacts.

2. Click Download.

3. Browse to the directory where you want to save the artifact.

4. Click Save.

#### 3.11.3. Uploading an artifact

You can upload an artifact from the local storage to a project in Business Central.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Artifacts.

2. Click Upload.

3. Click Choose File and browse to the directory from where you want to upload the artifact.

4. Click Upload.

   | If you are using a non-Maven artifact, first deploy the artifact to the Maven repository using the `mvn deploy` command and then refresh the artifact list in Business Central.

### 3.12. Archetype management

Business Central provides an archetype management feature that enables you to list, add, validate, set as default, and delete the archetypes. You can manage archetypes from the Archetypes page in Business Central. Archetypes are projects installed in Apache Maven repositories in which you can set or create a template structure if required.

For the most up-to-date and detailed information about archetypes, see the Introduction to Archetypes page.

#### 3.12.1. Listing archetypes

The Archetypes page lists all the archetypes that are added in Business Central. This list provides the detailed information about Group ID, Artifact ID, Version, Created Date, Status, and Actions of an archetype.

Prerequisites

- You have created an archetype and listed it in the Business Central Settings from the maven repository.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Archetypes.

   In the Status column, green icon indicates it is a valid archetype, red icon indicates it is an invalid archetype whereas blue icon indicates the corresponding archetype is the default one for the new spaces.

#### 3.12.2. Adding an archetype

You can add a new archetype to Business Central.

Prerequisites

- You have installed an archetype in the Maven repository.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Archetypes.

2. Click Add Archetype.

3. In the Add Archetype panel, enter the GAV attributes in the Group ID, Artifact ID, and Version fields respectively.

4. Click Add.

Business Central validates the newly added archetype and make it available to be used as a template in all the spaces.

#### 3.12.3. Managing additional features of an archetype

You can delete, set a default, and validate the archetypes from the Archetypes page in Business Central.

Prerequisites

- You have created an archetype and listed in the Business Central Settings from the Maven repository.

Procedure

1. In Business Central, select the Admin icon in the upper-right corner of the screen and select Archetypes.

2. From the Actions column, click the icon on the right side of an archetype.

   - Select Delete from the drop-down menu to delete an archetype from the list.

   - Select Validate from the drop-down menu to validate whether the archetype is valid or not.

     | When the Business Central is starting up, all the registered archetypes are automatically validated.

   - Select Set as default from the drop-down menu to set an archetype as a default for the new spaces.

#### 3.12.4. Creating a project using archetypes

You can use archetypes to create a project in Business Central. When you create a project in Business Central, it is added to the Git repository that is connected to your OptaPlanner installation.

Prerequisites

- You have created an archetype and listed it in the Business Central Settings from the Maven repository.

- You have set an archetype as default in your space in the Business Central.

Procedure

1. In Business Central, go to Menu → Design → Projects.

2. Select or create the space into which you want to add a new project from an archetype template.

3. Click Add Project.

4. Type the project name and description in the Name and Description fields respectively.

5. Click Configure Advanced Options.

6. Select the Based on template check box.

7. Select the archetype from drop-down options if required.

   The default archetype is already set in the space.

8. Click Add.

The Assets view of the project opens based on the selected archetype template.

#### 3.12.5. Managing archetypes using space settings in Business Central

When you add archetypes to Business Central, you can use them as templates in all the spaces. You can manage all the archetypes from the Settings tab, which is available in the space. This tab is visible only to users with the `admin` role.

Prerequisites

- You have installed an archetype in the Maven repository.

- You have created an archetype and listed it in the Business Central Settings from the Maven repository.

Procedure

1. In Business Central, go to Menu → Design → Projects.

2. Select or create the space into which you want to manage the archetypes. The default space is MySpace.

3. Click Settings.

4. To include or exclude the archetypes in the space, select the Include check box.

5. From the Actions column, click the icon on the right side of an archetype and select Set as default from the drop-down menu to set an archetype as a default for the space.

6. Click Save.

### 3.13. SSH keystore

This section provides an overview of the Business Central SSH keystore and includes a guide for platform users. It explains how to use the Business Central SSH keystore to register and use it’s SSH public keys.

#### 3.13.1. Introduction

Business Central includes an SSH keystore service to provide proper SSH authentication for users.

It provides a configurable default SSH keystore, extensible APIs to allow custom implementations, support for multiple SSH public keys formats, and a new UI available on the Admin page to enable users to register their SSH public keys.

##### 3.13.1.1. The default SSH keystore

The default SSH keystore included with Business Central provides a file-based storage mechanism to store users' SSH public keys.

By default, it uses Business Central `.security` folder as a root path. It is possible to use a custom storage path by setting the `appformer.ssh.keys.storage.folder` property to direct to a different folder.

The SSH public keys are stored in the `{securityFolderPath}/pkeys/{userName}/` folder structure.

Each SSH public key consists of a pair of files in the storage folder:

- {keyId}.pub: a file containing the SSH public key content. The file name determines the logic key ID on the system, so do not modify the file name during runtime. For example

      ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDmak4Wu23RZ6XmN94bOsqecZxuTa4RRhhQmHmTZjMB7HM57/90u/B/gB/GhsPEu1nAXL0npY56tT/MPQ8vRm2C2W9A7CzN5+z5yyL3W01YZy3kzslk77CjULjfhrcfQSL3b2sPG5jv5E5/nyC/swSytucwT/PE7aXTS9H6cHIKUdYPzIt94SHoBxWRIK7PJi9d+eLB+hmDzvbVa1ezu5a8yu2kcHi6NxxfI5iRj2rsceDTp0imC1jMoC6ZDfBvZSxL9FXTMwFdNnmTlJveBtv9nAbnAvIWlilS0VOkdj1s3GxBxeZYAcKbcsK9sJzusptk5dxGsG2Z8vInaglN6OaOQ7b7tcomzCYYwviGQ9gRX8sGsVrw39gsDIGYP2tA4bRr7ecHnlNg1b0HCchA5+QCDk4Hbz1UrnHmPA2Lg9c3WGm2qedvQdVJXuS3mlwYOqL40aXPs6890PvFJUlpiVSznF50djPnwsMxJZEf1HdTXgZD1Bh54ogZf7czyUNfkNkE69yJDbTHjpQd0cKUQnu9tVxqmBzhX31yF4VcsMeADcf2Z8wlA3n4LZnC/GwonYlq5+G93zJpFOkPhme8c2XuPuCXF795lsxyJ8SB/AlwPJAhEtm0y0s0l1l4eWqxsDxkBOgN+ivU0czrVMssHJEJb4o0FLf7iHhOW56/iMdD9w== userName

- .{keyId}.pub.meta: a file containing the key metadata in JSON format. If a key has no metadata, a new metadata file is dynamically generated. For example:

      {
          "name":"Key",
          "creationDate":"Oct 10, 2018 10:10:50 PM",
          "lastTimeUsed":"Oct 11, 2018 12:11:23 PM"
      }

##### 3.13.1.2. Using a custom SSH keystore

It is possible to extend and customize the platform default SSH keystore to meet more specific requirements.

Use the system property `appformer.ssh.keystore` to specify the Java class name of the service to use. If the property does not exist or it contains a wrong value, the default SSH keystore is loaded.

| To create a custom implementation of the SSH keystore, your Java Class must implement the class `org.uberfire.ssh.service.backend.keystore.SSHKeyStore` defined in the `uberfire-ssh-api` module.

#### 3.13.2. Using the SSH keystore

This section describes how to use the SSH keystore to register your own keys and how to use them.

##### 3.13.2.1. The SSH keystore UI

The SSH keystore provides an intuitive UI to enable users to manage their SSH public keys on the system. It is accessible from the Admin page by using the SSH Keys menu option.

Figure 84. SSH Keys Menu Option on Admin Page

After you click the SSH Keys menu option the SSH Keys Editor will open. the editor displays a table showing the user SSH public keys and provides access to the main action buttons.

- Add SSH Key: Used to add an SSH public key for the user.

  Figure 85. Adding new SSH public key

- Delete SSH Key: Used to remove an existing SSH public key

  Figure 86. Deleting a SSH public key

Figure 87. SSH keystore UI

##### 3.13.2.2. Adding SSH keys

This section explains step by step how to add an SSH public key to the SSH keystore.

###### Creating the SSH key on your computer

1. Open a terminal on your computer

2. Run the `ssh-keygen` command to create the key:

       ssh-keygen -t rsa -b 4096 -C "<your_user_login_here>"

   | The SSH key formats supported by the keystore are 'ssh-rsa', 'ssh-dss', 'ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384' and 'ecdsa-sha2-nistp521'.

3. When prompted, press Enter and accept the default key file location.

       Enter a file in which to save the key (/home/<your_login_here>/.ssh/id_rsa): [Press enter]

4. When prompted, enter the pass phrase that you want to use.

       Enter passphrase (empty for no passphrase): [Type a passphrase]
       Enter same passphrase again: [Type passphrase again]

5. Start the `ssh-agent`:

       eval "$(ssh-agent -s)"
       Agent pid <any-number-here>

6. Add the new SSH private key to the `ssh-agent`. If you used a different key name, replace `id_rsa` with your key name

       ssh-add ~/.ssh/id_rsa

###### Registering your SSH public key with the SSH keystore

1. In Business Central, go to the gear icon next to your login to open the Admin page.

   Figure 88. Accessing the Admin Page

2. Open the SSH keystore UI by clicking the SSH Keys menu option.

   Figure 89. SSH Keys Menu Option on Admin Page
   Figure 90. SSH Keystore UI Without keys

3. Copy the contents of your SSH Public key onto the clipboard. Use the `cat` command to display your key content. If you used a different key name: replace `id_rsa` with your key name, and copy it.

       cat ~/.ssh/id_rsa.pub

4. In the SSH keystore UI press the Add SSH Key button to open the New SSH public key form. Specify a name, copy the key content into the key field and click Add SSH Key to register the key.

   Figure 91. Adding new SSH public key

   | Name field cannot be empty, this field defines a meaningful name for the user to identify the key on the SSH public keys table. Key must be a valid SSH Public key, so it cannot be empty and the key format must be supported by the platform.

### 3.14. Embedding Business Central in Your Application

Apart from the individual perspectives (such as the Library or Content Management), Business Central provides a number of editors used for designing and managing assets in different formats. Within Business Central, each asset type has a corresponding editor.

Business Central provides the possibility to embed the perspectives and editors in the user’s application using the standalone mode. Without actually switching to Business Central, it is possible to display perspectives and edit various assets, such as rules, processes, or decision tables, in separate applications.

To embed a part of Business Central in an application, Business Central must be deployed and running on a web server or an application server. Then, in your application, include an HTML inline frame with the proper HTTP query parameters as described in the following table.

Table 3. HTTP query parameters for the standalone mode
Parameter | Values | Description
--- | --- | ---
`standalone` | none | This parameter must be included in each URL of a perspective or an editor that will be used in the standalone mode.
`perspective` | `LibraryPerspective`, `ContentManagerPerspective`, or any custom-created page | Used for specifying the perspective to be displayed.
`header` | `UberfireBreadcrumbsContainer` | Displays the breadcrumbs at the top of the page that can be used for navigating to the lists of spaces and projects within the Library. This parameter can be used only if `perspective=LibraryPerspective` is specified.
`path` | `default://master@MySpace/Shop/src/main/java/com/Product.java` | Specifies the path to the asset to be opened in a corresponding editor. The path must be specified in the format `default://BRANCH@SPACE/PROJECT/PATH_TO_ASSET/ASSET_NAME.FILE_EXTENSION`.

Table 4. Usage examples
URL | Description
--- | ---
http://localhost:8080/business-central/kie-wb.jsp?standalone&perspective=LibraryPerspective | Opens the Library where it is possible to select a project to be managed.
http://localhost:8080/business-central/kie-wb.jsp?standalone&perspective=LibraryPerspective&header=UberfireBreadcrumbsContainer | Opens the Library with the list of projects. The `header` parameter displays the breadcrumbs at the top of the page, which allow the user to switch between the spaces as well as the projects.
http://localhost:8080/business-central/kie-wb.jsp?standalone&path=default://master@MySpace/Shop/src/main/java/com/Product.java | Opens the editor of the specified asset.
http://localhost:8080/business-central/kie-wb.jsp?standalone&perspective=ContentManagerPerspective | Opens the Content Management perspective, where it is possible to create and manage custom pages.
http://localhost:8080/business-central/kie-wb.jsp?standalone&perspective=MyCustomPage | Opens the specified custom page that has been created before using the Content Management perspective. The value of the `perspective` parameter must correspond to the actual name of the page.

### 3.15. Execution Server Management UI

The Execution Server Management UI allows users create and modify Server Templates and Containers, it also allows users manage Remote Servers. This screen is available via Deploy → Rule Deployments menu.

Figure 92. Execution Server Management

| The management UI is only available for KIE Managed Servers.

#### 3.15.1. Server Templates

Server templates are used to define a common configuration that can be used for multiple servers, thus the name: Template.

Server Templates can be created directly from the management UI. A server template is automatically created when a server connects to the KIE Server controller and there isn’t a template definition for that remote server. Server templates may have one or more capabilities, such capabilities can’t be modified, if you need to modify the capabilities you’ll have to create a new template. Here is the list of current capabilities:

- Rule (Drools)

- Process (jBPM)

- Planning (Optaplanner)

| For Planner capability it’s mandatory to enable Rule’s capability too.

In order to create a new Server Template you have to click at New Server Template button and follow the wizard. It’s also possible to create a container during Wizard, but for now let’s limit to just the template.

Figure 93. New Server Template Wizard

Once created you’ll get the new Template listed on the left hand side, with the new Server Template highlighted. On the right hand side you get the 2nd level navigation that lists Containers and Remote Servers that are related to selected Server Template.

Figure 94. Server Templates

On top of the navigation is also possible to delete the current Server Template or create a copy of it.

Figure 95. Server Template Actions

#### 3.15.2. Container

A Container is a KIE Container configuration of the Server Template. Click the Add Container button to create a new container for the current Server Template.

The search area can help users find a specific KJAR that they are looking for.

Figure 96. New Container Wizard

For Server Templates that have Process capabilities enabled, the Wizard has a 2nd optional step where users can configure some process related behaviors.

Figure 97. Process Configuration

Kie Base Name determines which Kie Base of the deployed artifact will be used.

Kie Session Name determines which Kie Session of the selected Kie Base will be used.

| Please notice that configurations on this tab take effect only if the deployed project contains some business processes. It is not enough if the server template has the extension for processes enabled.

Once created the new Container will be displayed on the containers list just above the list of remote servers. Just after created a container is by default Stopped which is the only state that allows users to remove it.

Figure 98. Container

A Container has the following tabs available for management and/or configuration:

- Status

- Version Configuration

- Process Configuration

Status tab lists all the Remote Servers that are running the active Container. Each Remote Server is rendered as a Card, which displays to users status and endpoint.

| Only started Containers are deployed to remote servers.

Figure 99. Status Container

For containers that do not have process capability the Version Configuration tab allows users to change the current version of the Container. Users can upgrade manually to a specific version using the "Upgrade" button or enable/disable the Scanner. It’s also possible to execute a Scan Now operation that will scan for new versions only once.

To redeploy SNAPSHOT kjars with your latest changes all existing containers with that version must first be removed. Executing 'build and deploy' will then create a container with the latest SNAPSHOT kjar. However, this is not possible for release versions. Following maven release conventions if the GAV of a kjar is anything but SNAPSHOT, the GAV will need to be updated to the newer release version and deployed to its own container. The new release version can also be used to upgrade an existing container as described previously provided the container does not have process capability.

Figure 100. Version Configuration

Process Configuration is the same form that is displayed during New Container Wizard for Template Servers that have Process Capability. If Template Server doesn’t have such capability, the action buttons will be disabled.

Figure 101. Process Configuration

#### 3.15.3. Remote Server

Remote Server is a Managed KIE Server instance running that has a KIE Server controller configured.

| By default, Business Central comes with a KIE Server controller embedded.

The list of Remote Servers is displayed just under the list of Containers. Once selected the screens reveals the Remote Server details and a list of cards, each card represents a running Container.

Figure 102. Remote Servers

### 3.16. Experimental Features Framework

This section describes the Experimental Features Framework functionality and how to use it.

#### 3.16.1. Introduction

The Experimental Features Framework is a platform service that allows developers to deliver features which are still not part of Business Central (for example, ongoing developments, tech previews, POCs…​) and expose these features to users to let them have a preview of what is coming in the future.

The Experimental Features Framework provides the following features:

- New Editor UI, accessible on the Admin page, where users can enable and disable Experimental Features.

- Support for user-level features (stored as system preferences for each user) and global features (only available to `admin` users, in the editor)

- Ability to dynamically handle the visibility for different Experimental Resources on Business Central.

  - Business Central Perspectives

  - Business Central Screens

  - Business Central Editors

  - Library Asset Types

  - Page Builder Layout Components

#### 3.16.2. Types of Experimental Features

There are two types of Experimental Features, each with different scopes:

- User: This type of feature can be enabled or disabled for any platform user, making the feature available for a single user without affecting other users, storing the feature state as a user preference.

- Global: This type of feature is global for all users. Only users with administrator permissions user can enable them.

#### 3.16.3. Experimental Features Editor

The Experimental Features Framework provides an editor where users can configure the features that they want to use. To open the editor, navigate to the Admin page and click the Experimental menu option.

Figure 103. Experimental Features Menu Option

| The Experimental menu option only appears if the Experimental Features Framework is enabled and there are Experimental Features installed on Business Central

Figure 104. Experimental Features Editor

| The features and groups displayed on this documentation are examples.

The Experimental Features Editor displays all the Experimental Features installed on Business Central. For a better user experience these features are organized in collapsible groups. Click a label to expand or collapse a group.

Figure 105. Experimental Features Group

Each row inside of the group corresponds to an experimental feature. Click toggle button to enable or disable the feature.

You can also enable or disable all group features by clicking the group’s *Enable all" / "Disable all" button.

Figure 106. Enable all group features

#### 3.16.4. Enabling the Experimental Features Framework

By default, the Experimental Features Framework is disabled. You can enable it by starting Business Central and setting the system property `appformer.experimental.features=true`.

Any Experimental Feature present on Business Central will not be accessible to users while the Experimental Features Framework is disabled.

### 3.17. Business Central profiles

Starting on 7.15.0.Final, KIE Workbench is renamed to Business Central. Business Central contains all KIE Workbench features. To select between the set of available features, the concept of profiles is introduced. This chapter describes profiles and show how you can configure them in Business Central.

#### 3.17.1. Introduction

When you start the Business Central application, all the features are available to you by default. To configure a set of features, you can select from a list of profile.

A profile is a set of features which contains:

- Menus

- Resources that it can handle

- Specific home page

Currently, we have two profiles: * Full: All workbench features will be enabled (default); * Planner and Rules: Only Optaplanner and Drools features will be available.

#### 3.17.2. Selecting a profile

Profiles can be selected on Administration page, by selecting the Profiles preference.

| Only admin users have access to the Profiles preference.

Figure 107. Profile Menu Option

It is also possible to select a profile using the system property `org.kie.workbench.profile`, which can have the values `FULL` (for Full profile) and `PLANNER_AND_RULES` (For Planner and Rules profile).

### 3.18. Performance tuning considerations with Business Central

The following key concepts or suggested practices can help you optimize Business Central configuration and OptaPlanner performance. These concepts are summarized in this section as a convenience and are explained in more detail in the cross-referenced documentation, where applicable. This section will expand or change as needed with new releases of OptaPlanner.

Ensure that development mode is enabled during development

  You can set KIE Server or specific projects in Business Central to use `production` mode or `development` mode. By default, KIE Server and all new projects in Business Central are in development mode. This mode provides features that facilitate your development experience, such as flexible project deployment policies, and features that optimize KIE Server performance during development, such as disabled duplicate GAV detection. Use development mode until your OptaPlanner environment is established and completely ready for production mode.

  For more information about configuring the environment mode or duplicate GAV detection, see the following resources:

  - [_development_streamline_lifecycle]

  - Duplicate GAV detection

Disable verification and validation of complex guided decision tables

  The decision table verification and validation feature of Business Central is enabled by default. This feature helps you validate your guided decision tables, but with complex guided decision tables, this feature can hinder Drools engine performance. You can disable this feature by setting the `org.kie.verification.disable-dtable-realtime-verification` system property value to `true`.

  For more information about guided decision table validation, see [guided-decision-tables-validation-disable-proc]

Disable automatic builds if you have many large projects

  In Business Central, when you navigate between projects in the Project Explorer side panel, the selected project is built automatically so that the Alerts window is updated to show any build errors for the project. If you have large projects or frequently switch between many projects that are under active development, this feature can hinder Business Central and Drools engine performance.

  To disable automatic project builds, set the `org.kie.build.disable-project-explorer` system property to `true`.

## 4. Authoring Planning Assets

### 4.1. Solver Editor

The solver editor creates a solver configuration that can be run in the Execution Solver or plain Java code after the kjar is deployed.

| To see and use this editor, the user needs to have the `Resource Planner`.

Use the Validate button to validate the solver configuration. This will actually build a Solver, so most issues in your project will present itself then, without the need to deploy and run it.

By default, the solver configuration automatically scans for all planning entities and planning solution classes. If none are found (or too many), validation fails.

#### 4.1.1. Score Director Factory

Use the Score Director Factory configuration section to define a KIE base, which contains scoring rule definitions. Select one of the KIE sessions defined within the KIE base. The sessions can be managed in the Project Editor.

| Planner uses a default KIE session if none is specified.

#### 4.1.2. Termination Editor

By default, a time period that the Planner engine is given to solve a problem instance is not limited. While this might be enforced by some scenarios (e.g. real-time planning), it is useful to have a mechanism to control the total duration of the solving process.

Refer to OptaPlanner documentation for more information on supported termination types.

| Solver can be terminated manually using REST API of the KIE Server.

Use Add to create new termination element within selected logical group and pick termination type. Input field will be displayed based on the selection.

Termination elements are organized into a tree structure. The editor supports definition of logical groups (represented by termination type Nested termination), which join multiple termination elements using logical operators (And/Or). The scope of the operator is limited by the logical group in which it is defined.

Click Remove to remove the termination element from the termination tree. If the removal action is performed on the root element of a logical group, all its children will be removed as well.

#### 4.1.3. Phase Configuration

Planner splits the solving process into multiple phases. Every phase represents a single optimization algorithm run, which consumes a result returned by the previous phase. For example, a Construction Heuristic phase is usually placed before a Local Search phase to provide a good initial solution that the Local Search further optimizes.

| By default, the Solver uses a single Construction Heuristic phase followed by a Local Search phase.

Click Add to add a new phase. Individual phase elements provide additional configuration options. Click Remove to remove a specific phase from the Solver configuration.

### 4.2. Domain Editor

Planner leverages Data modeller to create domain model for constraint satisfaction problems.

In addition to the basic functionality the Data modeller provides (creating data objects and their properties), Business Central allows enhancing the data model with Planner-specific data object roles (Planning Solution, Planning Entity) in a user-friendly way. The options are available in the Planner dock.

The content of the dock varies depending on the current selection. Selecting a data object results in displaying top-level settings defined on data object level (Planning Solution, Planning Entity). On the other hand, selecting properties of the data object results in displaying fine-grained settings defined on property level of the data object.

The overview of the Planner dock capabilities is shown in the following division:

Data object level

- None

- Planning Entity

  - Use difficulty comparator for sorting planning entities

- Planning Solution

  - Solution Score Type

Property level

- None

- Planning Entity

  - Planning Variable

  - valueRangeId

- Planning Solution

  - Planning Value Range Provider

  - Planning Value Range Provider id

  - Planning Entity Collection

#### 4.2.1. Planning Entity Difficulty Comparator

Specified on Planning entity level, the Difficulty comparator provides a way to determine which Planning entities are more difficult to plan. This helps optimization algorithms to work in an efficient manner. Refer to OptaPlanner documentation for more details.

The Difficulty comparator definition tool is present in the Planner dock of the Data modeler and becomes available once a PlanningEntity selection is performed on a data object.

Click Add condition to add new sorting criteria for given planning entity. Once the criterion is added, Clicking Add field allows the user to select fields which will be used for difficulty comparison.

There are 2 types of fields:

- Basic - value types (e.g. number, String)

- Data object - complex types having nested attributes

Data object types allow nesting deep into object hierarchy, until a basic type is encountered. In this situation Add field button is no longer displayed. Sorting criteria are ordered. The ones defined first are prioritized when the Planner engine resolves planning entity difficulty.

Click the Remove icon within a label to remove the field from the sorting criteria. If the field is of type Data object, all its children are removed as well.

Click Arrow up, Arrow down to change the priority of the criterion by moving it up/down.

Select Sort order icon to define whether given criterion should be applied to sort the planning entities in ascending or descending order.

### 4.3. Guided Rule Editor

To solve an optimization problem, define score constraints that evaluate your solution. Planner integrates with the Guided Rule Editor and provides score modifiers which are used by the Planner engine during the solving process.

Score modifiers can be accessed in the action selector (+) of the THEN (right-hand side) section of a rule, provided the Planning Solution is defined within the project.

| Make sure to define a Planning Solution before proceeding to a rule creation.

There are two types of Planner actions in the Guided Rule Editor:

- Modify a single score level - use the action to modify only one score component (e.g. hard score)

- Modify multiple score levels - use the action to modify multiple score components at the same time (e.g. hard and soft score)

Once the action is selected, Planner score input appears on the THEN (right-hand side) section of the rule. Insert the value of a constraint into the text input. Click Validate to verify the correctness of the inserted value.

## 5. Business Central integration

### 5.1. Knowledge Store REST API for Business Central spaces and projects

OptaPlanner provides a Knowledge Store REST API that you can use to interact with your projects and spaces in OptaPlanner without using the Business Central user interface. The Knowledge Store is the artifact repository for assets in OptaPlanner. This API support enables you to facilitate and automate maintenance of Business Central projects and spaces.

With the Knowledge Store REST API, you can perform the following actions:

- Retrieve information about all projects and spaces

- Create, update, or delete projects and spaces

- Build, deploy, and test projects

- Retrieve information about previous Knowledge Store REST API requests, or jobs

Knowledge Store REST API requests require the following components:

Authentication

  The Knowledge Store REST API requires HTTP Basic authentication or token-based authentication for the user role `rest-all`. To view configured user roles for your OptaPlanner distribution, navigate to `~/$SERVER_HOME/standalone/configuration/application-roles.properties` and `~/application-users.properties`.

  To add a user with the `rest-all` role, navigate to `~/$SERVER_HOME/bin` and run the following command:

      $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['rest-all'])"

  For more information about user roles and OptaPlanner installation options, see

HTTP headers

  The Knowledge Store REST API requires the following HTTP headers for API requests:

  - `Accept`: Data format accepted by your requesting client:

    - `application/json` (JSON)

  - `Content-Type`: Data format of your `POST` or `PUT` API request data:

    - `application/json` (JSON)

HTTP methods

  The Knowledge Store REST API supports the following HTTP methods for API requests:

  - `GET`: Retrieves specified information from a specified resource endpoint

  - `POST`: Creates or updates a resource

  - `PUT`: Updates a resource

  - `DELETE`: Deletes a resource

Base URL

  The base URL for Knowledge Store REST API requests is `http://SERVER:PORT/business-central/rest/`, such as `http://localhost:8080/business-central/rest/`.

  | The REST API base URL for the Knowledge Store and for the KIE Server controller built in to Business Central are the same because both are considered part of Business Central REST services.

Endpoints

  Knowledge Store REST API endpoints, such as `/spaces/{spaceName}` for a specified space, are the URIs that you append to the Knowledge Store REST API base URL to access the corresponding resource or type of resource in OptaPlanner.

  Example request URL for `/spaces/{spaceName}` endpoint

  `http://localhost:8080/business-central/rest/spaces/MySpace`

Request data

  HTTP `POST` requests in the Knowledge Store REST API may require a JSON request body with data to accompany the request.

  Example POST request URL and JSON request body data

  `http://localhost:8080/business-central/rest/spaces/MySpace/projects`

      {
        "name": "Employee_Rostering",
        "groupId": "employeerostering",
        "version": "1.0.0-SNAPSHOT",
        "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill."
      }

#### 5.1.1. Sending requests with the Knowledge Store REST API using a REST client or curl utility

The Knowledge Store REST API enables you to interact with your projects and spaces in OptaPlanner without using the Business Central user interface. You can send Knowledge Store REST API requests using any REST client or curl utility.

Prerequisites

- Business Central is installed and running.

- You have `rest-all` user role access to Business Central.

Procedure

1. Identify the relevant API endpoint to which you want to send a request, such as `[GET] /spaces` to retrieve spaces in Business Central.

2. In a REST client or curl utility, enter the following components for a `GET` request to `/spaces`. Adjust any request details according to your use case.

   For REST client:

   - Authentication: Enter the user name and password of the Business Central user with the `rest-all` role.

   - HTTP Headers: Set the following header:

     - `Accept`: `application/json`

   - HTTP method: Set to `GET`.

   - URL: Enter the Knowledge Store REST API base URL and endpoint, such as `http://localhost:8080/business-central/rest/spaces`.

   For curl utility:

   - `-u`: Enter the user name and password of the Business Central user with the `rest-all` role.

   - `-H`: Set the following header:

     - `Accept`: `application/json`

   - `-X`: Set to `GET`.

   - URL: Enter the Knowledge Store REST API base URL and endpoint, such as `http://localhost:8080/business-central/rest/spaces`.

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -X GET "http://localhost:8080/business-central/rest/spaces"

3. Execute the request and review the KIE Server response.

   Example server response (JSON):

       [
         {
           "name": "MySpace",
           "description": null,
           "projects": [
             {
               "name": "Employee_Rostering",
               "spaceName": "MySpace",
               "groupId": "employeerostering",
               "version": "1.0.0-SNAPSHOT",
               "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill.",
               "publicURIs": [
                 {
                   "protocol": "git",
                   "uri": "git://localhost:9418/MySpace/example-Employee_Rostering"
                 },
                 {
                   "protocol": "ssh",
                   "uri": "ssh://localhost:8001/MySpace/example-Employee_Rostering"
                 }
               ]
             },
             {
               "name": "Mortgage_Process",
               "spaceName": "MySpace",
               "groupId": "mortgage-process",
               "version": "1.0.0-SNAPSHOT",
               "description": "Getting started loan approval process in BPMN2, decision table, business rules, and forms.",
               "publicURIs": [
                 {
                   "protocol": "git",
                   "uri": "git://localhost:9418/MySpace/example-Mortgage_Process"
                 },
                 {
                   "protocol": "ssh",
                   "uri": "ssh://localhost:8001/MySpace/example-Mortgage_Process"
                 }
               ]
             }
           ],
           "owner": "admin",
           "defaultGroupId": "com.myspace"
         },
         {
           "name": "MySpace2",
           "description": null,
           "projects": [
             {
               "name": "IT_Orders",
               "spaceName": "MySpace",
               "groupId": "itorders",
               "version": "1.0.0-SNAPSHOT",
               "description": "Case Management IT Orders project",
               "publicURIs": [
                 {
                   "protocol": "git",
                   "uri": "git://localhost:9418/MySpace/example-IT_Orders-1"
                 },
                 {
                   "protocol": "ssh",
                   "uri": "ssh://localhost:8001/MySpace/example-IT_Orders-1"
                 }
               ]
             }
           ],
           "owner": "admin",
           "defaultGroupId": "com.myspace"
         }
       ]

4. In your REST client or curl utility, send another API request with the following components for a `POST` request to `/spaces/{spaceName}/projects` to create a project within a space. Adjust any request details according to your use case.

   For REST client:

   - Authentication: Enter the user name and password of the Business Central user with the `rest-all` role.

   - HTTP Headers: Set the following header:

     - `Accept`: `application/json`

     - `Accept-Language`: `en-US`

     - `Content-Type`: `application/json`

   - HTTP method: Set to `POST`.

   - URL: Enter the Knowledge Store REST API base URL and endpoint, such as `http://localhost:8080/business-central/rest/spaces/MySpace/projects`.

   - Request body: Add a JSON request body with the identification data for the new project:

       {
         "name": "Employee_Rostering",
         "groupId": "employeerostering",
         "version": "1.0.0-SNAPSHOT",
         "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill."
       }

   For curl utility:

   - `-u`: Enter the user name and password of the Business Central user with the `rest-all` role.

   - `-H`: Set the following headers:

     - `Accept`: `application/json`

     - `Accept-Language`: `en-US` (If not defined, the default locale from the JVM is reflected)

     - `Content-Type`: `application/json`

   - `-X`: Set to `POST`.

   - URL: Enter the Knowledge Store REST API base URL and endpoint, such as `http://localhost:8080/business-central/rest/spaces/MySpace/projects`.

   - `-d`: Add a JSON request body or file (`@file.json`) with the identification data for the new project:

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -H "Accept-Language: en-US" -H "Content-Type: application/json" -X POST "http://localhost:8080/business-central/rest/spaces/MySpace/projects" -d "{ \"name\": \"Employee_Rostering\", \"groupId\": \"employeerostering\", \"version\": \"1.0.0-SNAPSHOT\", \"description\": \"Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill.\"}"

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -H "Accept-Language: en-US" -H "Content-Type: application/json" -X POST "http://localhost:8080/business-central/rest/spaces/MySpace/projects" -d @my-project.json

5. Execute the request and review the KIE Server response.

   Example server response (JSON):

       {
         "jobId": "1541017411591-6",
         "status": "APPROVED",
         "spaceName": "MySpace",
         "projectName": "Employee_Rostering",
         "projectGroupId": "employeerostering",
         "projectVersion": "1.0.0-SNAPSHOT",
         "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill."
       }

   If you encounter request errors, review the returned error code messages and adjust your request accordingly.

#### 5.1.2. Supported Knowledge Store REST API endpoints

The Knowledge Store REST API provides endpoints for managing spaces and projects in OptaPlanner and for retrieving information about previous Knowledge Store REST API requests, or jobs.

##### 5.1.2.1. Spaces

The Knowledge Store REST API supports the following endpoints for managing spaces in Business Central. The Knowledge Store REST API base URL is `http://SERVER:PORT/business-central/rest/`. All requests require HTTP Basic authentication or token-based authentication for the `rest-all` user role.

[GET] /spaces

  Returns all spaces in Business Central.

  Example server response (JSON)

      [
        {
          "name": "MySpace",
          "description": null,
          "projects": [
            {
              "name": "Employee_Rostering",
              "spaceName": "MySpace",
              "groupId": "employeerostering",
              "version": "1.0.0-SNAPSHOT",
              "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill.",
              "publicURIs": [
                {
                  "protocol": "git",
                  "uri": "git://localhost:9418/MySpace/example-Employee_Rostering"
                },
                {
                  "protocol": "ssh",
                  "uri": "ssh://localhost:8001/MySpace/example-Employee_Rostering"
                }
              ]
            },
            {
              "name": "Mortgage_Process",
              "spaceName": "MySpace",
              "groupId": "mortgage-process",
              "version": "1.0.0-SNAPSHOT",
              "description": "Getting started loan approval process in BPMN2, decision table, business rules, and forms.",
              "publicURIs": [
                {
                  "protocol": "git",
                  "uri": "git://localhost:9418/MySpace/example-Mortgage_Process"
                },
                {
                  "protocol": "ssh",
                  "uri": "ssh://localhost:8001/MySpace/example-Mortgage_Process"
                }
              ]
            }
          ],
          "owner": "admin",
          "defaultGroupId": "com.myspace"
        },
        {
          "name": "MySpace2",
          "description": null,
          "projects": [
            {
              "name": "IT_Orders",
              "spaceName": "MySpace",
              "groupId": "itorders",
              "version": "1.0.0-SNAPSHOT",
              "description": "Case Management IT Orders project",
              "publicURIs": [
                {
                  "protocol": "git",
                  "uri": "git://localhost:9418/MySpace/example-IT_Orders-1"
                },
                {
                  "protocol": "ssh",
                  "uri": "ssh://localhost:8001/MySpace/example-IT_Orders-1"
                }
              ]
            }
          ],
          "owner": "admin",
          "defaultGroupId": "com.myspace"
        }
      ]

[GET] /spaces/{spaceName}

  Returns information about a specified space.

  Table 5. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space to be retrieved | String | Required

  Example server response (JSON)

      {
        "name": "MySpace",
        "description": null,
        "projects": [
          {
            "name": "Mortgage_Process",
            "spaceName": "MySpace",
            "groupId": "mortgage-process",
            "version": "1.0.0-SNAPSHOT",
            "description": "Getting started loan approval process in BPMN2, decision table, business rules, and forms.",
            "publicURIs": [
              {
                "protocol": "git",
                "uri": "git://localhost:9418/MySpace/example-Mortgage_Process"
              },
              {
                "protocol": "ssh",
                "uri": "ssh://localhost:8001/MySpace/example-Mortgage_Process"
              }
            ]
          },
          {
            "name": "Employee_Rostering",
            "spaceName": "MySpace",
            "groupId": "employeerostering",
            "version": "1.0.0-SNAPSHOT",
            "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill.",
            "publicURIs": [
              {
                "protocol": "git",
                "uri": "git://localhost:9418/MySpace/example-Employee_Rostering"
              },
              {
                "protocol": "ssh",
                "uri": "ssh://localhost:8001/MySpace/example-Employee_Rostering"
              }
            ]
          },
          {
            "name": "Evaluation_Process",
            "spaceName": "MySpace",
            "groupId": "evaluation",
            "version": "1.0.0-SNAPSHOT",
            "description": "Getting started Business Process for evaluating employees",
            "publicURIs": [
              {
                "protocol": "git",
                "uri": "git://localhost:9418/MySpace/example-Evaluation_Process"
              },
              {
                "protocol": "ssh",
                "uri": "ssh://localhost:8001/MySpace/example-Evaluation_Process"
              }
            ]
          },
          {
            "name": "IT_Orders",
            "spaceName": "MySpace",
            "groupId": "itorders",
            "version": "1.0.0-SNAPSHOT",
            "description": "Case Management IT Orders project",
            "publicURIs": [
              {
                "protocol": "git",
                "uri": "git://localhost:9418/MySpace/example-IT_Orders"
              },
              {
                "protocol": "ssh",
                "uri": "ssh://localhost:8001/MySpace/example-IT_Orders"
              }
            ]
          }
        ],
        "owner": "admin",
        "defaultGroupId": "com.myspace"
      }

[POST] /spaces

  Creates a space in Business Central.

  Table 6. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  body | The `name`, `description`, `owner`, `defaultGroupId`, and any other components of the new space | Request body | Required

  Example request body (JSON)

      {
        "name": "NewSpace",
        "description": "My new space.",
        "owner": "admin",
        "defaultGroupId": "com.newspace"
      }

  Example server response (JSON)

      {
        "jobId": "1541016978154-3",
        "status": "APPROVED",
        "spaceName": "NewSpace",
        "owner": "admin",
        "defaultGroupId": "com.newspace",
        "description": "My new space."
      }

[PUT] /spaces

  Updates `description`, `owner`, and `defaultGroupId` of a space in Business Central.

  Example request body (JSON)

      {
        "name": "MySpace",
        "description": "This is updated description",
        "owner": "admin",
        "defaultGroupId": "com.updatedGroupId"
      }

  Example server response (JSON)

      {
        "jobId": "1592214574454-1",
        "status": "APPROVED",
        "spaceName": "MySpace",
        "owner": "admin",
        "defaultGroupId": "com.updatedGroupId",
        "description": "This is updated description"
      }

[DELETE] /spaces/{spaceName}

  Deletes a specified space from Business Central.

  Table 7. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space to be deleted | String | Required

  Example server response (JSON)

      {
        "jobId": "1541127032997-8",
        "status": "APPROVED",
        "spaceName": "MySpace",
        "owner": "admin",
        "description": "My deleted space.",
        "repositories": null
      }

##### 5.1.2.2. Projects

The Knowledge Store REST API supports the following endpoints for managing, building, and deploying projects in Business Central. The Knowledge Store REST API base URL is `http://SERVER:PORT/business-central/rest/`. All requests require HTTP Basic authentication or token-based authentication for the `rest-all` user role.

[GET] /spaces/{spaceName}/projects

  Returns projects in a specified space.

  Table 8. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space for which you are retrieving projects | String | Required

  Example server response (JSON)

      [
        {
          "name": "Mortgage_Process",
          "spaceName": "MySpace",
          "groupId": "mortgage-process",
          "version": "1.0.0-SNAPSHOT",
          "description": "Getting started loan approval process in BPMN2, decision table, business rules, and forms.",
          "publicURIs": [
            {
              "protocol": "git",
              "uri": "git://localhost:9418/MySpace/example-Mortgage_Process"
            },
            {
              "protocol": "ssh",
              "uri": "ssh://localhost:8001/MySpace/example-Mortgage_Process"
            }
          ]
        },
        {
          "name": "Employee_Rostering",
          "spaceName": "MySpace",
          "groupId": "employeerostering",
          "version": "1.0.0-SNAPSHOT",
          "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill.",
          "publicURIs": [
            {
              "protocol": "git",
              "uri": "git://localhost:9418/MySpace/example-Employee_Rostering"
            },
            {
              "protocol": "ssh",
              "uri": "ssh://localhost:8001/MySpace/example-Employee_Rostering"
            }
          ]
        },
        {
          "name": "Evaluation_Process",
          "spaceName": "MySpace",
          "groupId": "evaluation",
          "version": "1.0.0-SNAPSHOT",
          "description": "Getting started Business Process for evaluating employees",
          "publicURIs": [
            {
              "protocol": "git",
              "uri": "git://localhost:9418/MySpace/example-Evaluation_Process"
            },
            {
              "protocol": "ssh",
              "uri": "ssh://localhost:8001/MySpace/example-Evaluation_Process"
            }
          ]
        },
        {
          "name": "IT_Orders",
          "spaceName": "MySpace",
          "groupId": "itorders",
          "version": "1.0.0-SNAPSHOT",
          "description": "Case Management IT Orders project",
          "publicURIs": [
            {
              "protocol": "git",
              "uri": "git://localhost:9418/MySpace/example-IT_Orders"
            },
            {
              "protocol": "ssh",
              "uri": "ssh://localhost:8001/MySpace/example-IT_Orders"
            }
          ]
        }
      ]

[GET] /spaces/{spaceName}/projects/{projectName}

  Returns information about a specified project in a specified space.

  Table 9. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project to be retrieved | String | Required

  Example server response (JSON)

      {
        "name": "Employee_Rostering",
        "spaceName": "MySpace",
        "groupId": "employeerostering",
        "version": "1.0.0-SNAPSHOT",
        "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill.",
        "publicURIs": [
          {
            "protocol": "git",
            "uri": "git://localhost:9418/MySpace/example-Employee_Rostering"
          },
          {
            "protocol": "ssh",
            "uri": "ssh://localhost:8001/MySpace/example-Employee_Rostering"
          }
        ]
      }

[POST] /spaces/{spaceName}/projects

  Creates a project in a specified space.

  Table 10. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space in which the new project will be created | String | Required
  body | The `name`, `groupId`, `version`, `description`, and any other components of the new project | Request body | Required

  Example request body (JSON)

      {
        "name": "Employee_Rostering",
        "groupId": "employeerostering",
        "version": "1.0.0-SNAPSHOT",
        "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill."
      }

  Example server response (JSON)

      {
        "jobId": "1541017411591-6",
        "status": "APPROVED",
        "spaceName": "MySpace",
        "projectName": "Employee_Rostering",
        "projectGroupId": "employeerostering",
        "projectVersion": "1.0.0-SNAPSHOT",
        "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill."
      }

[DELETE] /spaces/{spaceName}/projects/{projectName}

  Deletes a specified project from a specified space.

  Table 11. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project to be deleted | String | Required

  Example server response (JSON)

      {
        "jobId": "1541128617727-10",
        "status": "APPROVED",
        "projectName": "Employee_Rostering",
        "spaceName": "MySpace"
      }

[POST] /spaces/{spaceName}/git/clone

  Clones a project into a specified space from a specified Git address.

  Table 12. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space to which you are cloning a project | String | Required
  body | The `name`, `description`, and Git repository `userName`, `password`, and `gitURL` for the project to be cloned | Request body | Required

  Example request body (JSON)

      {
        "name": "Employee_Rostering",
        "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill.",
        "userName": "baAdmin",
        "password": "password@1",
        "gitURL": "git://localhost:9418/MySpace/example-Employee_Rostering"
      }

  Example server response (JSON)

      {
        "jobId": "1541129488547-13",
        "status": "APPROVED",
        "cloneProjectRequest": {
          "name": "Employee_Rostering",
          "description": "Employee rostering problem optimisation using Planner. Assigns employees to shifts based on their skill.",
          "userName": "baAdmin",
          "password": "password@1",
          "gitURL": "git://localhost:9418/MySpace/example-Employee_Rostering"
        },
        "spaceName": "MySpace2"
      }

[POST] /spaces/{spaceName}/projects/{projectName}/maven/compile

  Compiles a specified project in a specified space (equivalent to `mvn compile`).

  Table 13. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project to be compiled | String | Required

  Example server response (JSON)

      {
        "jobId": "1541128617727-10",
        "status": "APPROVED",
        "projectName": "Employee_Rostering",
        "spaceName": "MySpace"
      }

[POST] /spaces/{spaceName}/projects/{projectName}/maven/test

  Tests a specified project in a specified space (equivalent to `mvn test`).

  Table 14. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project to be tested | String | Required

  Example server response (JSON)

      {
        "jobId": "1541132591595-19",
        "status": "APPROVED",
        "projectName": "Employee_Rostering",
        "spaceName": "MySpace"
      }

[POST] /spaces/{spaceName}/projects/{projectName}/maven/install

  Installs a specified project in a specified space (equivalent to `mvn install`).

  Table 15. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project to be installed | String | Required

  Example server response (JSON)

      {
        "jobId": "1541132668987-20",
        "status": "APPROVED",
        "projectName": "Employee_Rostering",
        "spaceName": "MySpace"
      }

[POST] /spaces/{spaceName}/projects/{projectName}/maven/deploy

  Deploys a specified project in a specified space (equivalent to `mvn deploy`).

  Table 16. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project to be deployed | String | Required

  Example server response (JSON)

      {
        "jobId": "1541132816435-21",
        "status": "APPROVED",
        "projectName": "Employee_Rostering",
        "spaceName": "MySpace"
      }

##### 5.1.2.3. Jobs (API requests)

All `POST` and `DELETE` requests in the Knowledge Store REST API return a job ID associated with each request, in addition to the returned request details. You can use a job ID to view the request status or delete a sent request.

Knowledge Store REST API requests, or jobs, can have the following statuses:

Table 17. Job statuses (API request statuses)
Status | Description
--- | ---
`ACCEPTED` | The request was accepted and is being processed.
`BAD_REQUEST` | The request contained incorrect content and was not accepted.
`RESOURCE_NOT_EXIST` | The requested resource (path) does not exist.
`DUPLICATE_RESOURCE` | The resource already exists.
`SERVER_ERROR` | An error occurred in KIE Server.
`SUCCESS` | The request finished successfully.
`FAIL` | The request failed.
`APPROVED` | The request was approved.
`DENIED` | The request was denied.
`GONE` | The job ID for the request could not be found due to one of the following reasons: The request was explicitly removed. The request finished and has been deleted from a status cache. A request is removed from a status cache after the cache has reached its maximum capacity. The request never existed.

The Knowledge Store REST API supports the following endpoints for retrieving or deleting sent API requests. The Knowledge Store REST API base URL is `http://SERVER:PORT/business-central/rest/`. All requests require HTTP Basic authentication or token-based authentication for the `rest-all` user role.

[GET] /jobs/{jobId}

  Returns the status of a specified job (a previously sent API request).

  Table 18. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `jobId` | ID of the job to be retrieved (example: `1541010216919-1`) | String | Required

  Example server response (JSON)

      {
        "status": "SUCCESS",
        "jobId": "1541010216919-1",
        "result": null,
        "lastModified": 1541010218352,
        "detailedResult": [
          "level:INFO, path:null, text:Build of module 'Mortgage_Process' (requested by system) completed.\n Build: SUCCESSFUL"
        ]
      }

[DELETE] /jobs/{jobId}

  Deletes a specified job (a previously sent API request). If the job is not being processed yet, this request removes the job from the job queue. This request does not cancel or stop an ongoing job.

  Table 19. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `jobId` | ID of the job to be deleted (example: `1541010216919-1`) | String | Required

  Example server response (JSON)

      {
        "status": "GONE",
        "jobId": "1541010216919-1",
        "result": null,
        "lastModified": 1541132054916,
        "detailedResult": [
          "level:INFO, path:null, text:Build of module 'Mortgage_Process' (requested by system) completed.\n Build: SUCCESSFUL"
        ]
      }

##### 5.1.2.4. Branches

The Knowledge Store REST API supports the following endpoints for managing branches in Business Central. The Knowledge Store REST API base URL is `http://SERVER:PORT/business-central/rest/`. All requests require HTTP Basic authentication or token-based authentication for the `rest-all` user role.

[GET] /spaces/{spaceName}/projects/{projectName}/branches

  Returns all branches in a specified project and space.

  Table 20. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space for which you are retrieving projects | String | Required
  `projectName` | Name of the project for which you are retrieving branches | String | Required

  Example server response (JSON)

      [
        {
          "name":"master"
        }
      ]

[POST] /spaces/{spaceName}/projects/{projectName}/branches

  Adds a specified branch in a specified project and space.

  Table 21. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project in which the new branch needs to be created | String | Required
  body | The `newBranchName` and `baseBranchName` of a project | Request body | Required

  Example request body (JSON)

      {
         "newBranchName":  "branch01",
         "baseBranchName": "master"
      }

  Example server response (JSON)

      {
          "jobId":          "1576175811141-3",
          "status":         "APPROVED",
          "spaceName":      "Space123",
          "projectName":    "ProjABC",
          "newBranchName":  "b1",
          "baseBranchName": "master",
          "userIdentifier": "bc"
      }

[DELETE] /spaces/{spaceName}/projects/{projectName}/branches/{branchName}

  Deletes a specified branch in a specified project and space.

  Table 22. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project where the branch is located | String | Required
  `branchName` | Name of the branch to be deleted | String | Required

  Example server response (JSON)

      {
          "jobId":          "1576175811421-5",
          "status":         "APPROVED",
          "spaceName":      "Space123",
          "projectName":    "ProjABC",
          "branchName":     "b1",
          "userIdentifier": "bc"
      }

[POST] /spaces/{spaceName}/projects/{projectName}/branches/{branchName}/maven/compile

  Compiles a specified branch in a specified project and space. If `branchName` is not specified, then request applies to the master branch.

  Table 23. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project where the branch is located | String | Required
  `branchName` | Name of the branch to be compiled | String | Required

  Example server response (JSON)

      {
          "jobId":       "1576175811233-4",
          "status":      "APPROVED",
          "spaceName":   "Space123",
          "projectName": "ProjABC",
          "branchName":  "b1",
      }

[POST] /spaces/{spaceName}/projects/{projectName}/branches/{branchName}/maven/install

  Installs a specified branch in a specified project and space. If `branchName` is not specified, then request applies to the master branch.

  Table 24. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project where the branch is located | String | Required
  `branchName` | Name of the branch to be installed | String | Required

  Example server response (JSON)

      {
          "jobId":       "1576175811233-4",
          "status":      "APPROVED",
          "spaceName":   "Space123",
          "projectName": "ProjABC",
          "branchName":  "b1",
      }

[POST] /spaces/{spaceName}/projects/{projectName}/branches/{branchName}/maven/test

  Tests a specified branch in a specified project and space. If `branchName` is not specified, then request applies to the master branch.

  Table 25. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project located | String | Required
  `projectName` | Name of the project where the branch is located | String | Required
  `branchName` | Name of the branch to be tested | String | Required

  Example server response (JSON)

      {
          "jobId":       "1576175811233-4",
          "status":      "APPROVED",
          "spaceName":   "Space123",
          "projectName": "ProjABC",
          "branchName":  "b1",
      }

[POST] /spaces/{spaceName}/projects/{projectName}/branches/{branchName}/maven/deploy

  Deploys a specified branch in a specified project and space. If `branchName` is not specified, then request applies to the master branch.

  Table 26. Request parameters
  Name | Description | Type | Requirement
  --- | --- | --- | ---
  `spaceName` | Name of the space where the project is located | String | Required
  `projectName` | Name of the project where the branch is located | String | Required
  `branchName` | Name of the branch to be deployed | String | Required

  Example server response (JSON)

      {
          "jobId":       "1576175811233-4",
          "status":      "APPROVED",
          "spaceName":   "Space123",
          "projectName": "ProjABC",
          "branchName":  "b1",
      }

### 5.2. Embedded KIE Server controller calls

When running Business Central with the embedded KIE Server controller mode, a series of endpoints related to managing all aspects of KIE Server templates, instances, and containers are also available. For more details, see KIE Server controller REST API. A Java client API is also available for interacting with these endpoints.

### 5.3. Keycloak SSO integration

Single Sign On (SSO) and related token exchange mechanisms are becoming the most common scenario for the authentication and authorization in different environments on the web, especially when moving into the cloud.

This section talks about the integration of Keycloak with jBPM or Drools applications in order to use all the features provided on Keycloak. Keycloak is an integrated SSO and IDM for browser applications and RESTful web services. Lean more about it in the Keycloak’s home page.

The result of the integration with Keycloak has lots of advantages such as:

- Provide an integrated SSO and IDM environment for different clients, including Business Central

- Social logins - use your Facebook, Google, LinkedIn, etc accounts

- User session management

- And much more…​

Next sections cover the following integration points with Keycloak:

- Business Central authentication through a Keycloak server

  It basically consists of securing both web client and remote service clients through the Keycloak SSO. So either web interface or remote service consumers (whether a user or a service) will authenticate into trough KC.

- Execution server authentication through a Keycloak server

  Consists of securing the remote services provided by the execution server (as it does not provide web interface). Any remote service consumer (whether a user or a service) will authenticate trough KC.

- Consuming remote services

  This section describes how a third party clients can consume the remote service endpoints provided by both Business Central and Execution Server, such as the REST API or remote file system services.

- Keycloak and Business Central’s security administration area

#### 5.3.1. Scenario

Consider the following diagram as the environment for this document’s example:

Keycloak is a standalone process that provides remote authentication, authorization and administration services that can be potentially consumed by one or more jBPM applications over the network.

Consider these main steps for building this environment:

- Install and set up a Keycloak server

- Create and set up a Realm for this example - Configure realm’s clients, users and roles

- Install and set up the SSO client adapter & jBPM application

Note: The resulting environment and the different configurations for this document are based on Business Central.

#### 5.3.2. Install and set up a Keycloak server

Keycloak provides an extensive documentation and several articles about the installation on different environments. This section describes the minimal setup for being able to build an integrated environment for the example. Please refer to the Keycloak documentation if you need more information.

Here are the steps for a minimal Keycloak installation and set up:

- Download the latest version of Keycloak from the Downloads section. This example is based on Keycloak 1.9.0.Final

- Unzip the downloaded distribution of Keycloak into a folder, let’s refer to it as

      $KC_HOME

- Run the KC server - This example is based on running both Keycloak and jBPM on same host. In order to avoid port conflicts you can use a port offset for the Keycloak’s server as:

      $KC_HOME/bin/standalone.sh -Djboss.socket.binding.port-offset=100

- Create a Keycloak’s administration 'admin' user by navigating to http://localhost:8180/auth/

The Keycloak administration console will be available at http://localhost:8180/auth/admin/.

#### 5.3.3. Create and set up the demo realm

Security realms are used to restrict the access for the different application’s resources.

Once the Keycloak server is running next step is about creating a realm. This realm will provide the different users, roles, sessions, etc for the jBPM application/s.

Keycloak provides several examples for the realm creation and management, from the official examples to different articles with more examples.

Follow these steps in order to create the demo realm used later in this document:

- Go to the Keycloak administration console and click Add realm button. Give it the name demo.

- Go to the Clients section (from the main admin console menu) and create a new client for the demo realm:

  - Client ID: kie

  - Client protocol: openid-connect

  - Access type: confidential

  - Root URL: http://localhost:8080

  - Base URL: /business-central-x.y.z.Final

  - Redirect URIs: /business-central-x.y.z.Final/*

The resulting kie client settings screen:

| As you can see in the above settings it’s being considered the value business-central-x.y.z.Final for the application’s context path. If your jBPM application will be deployed on a different context path, host or port, just use your concrete settings here.

Last step for being able to use the demo realm from Business Central is to create the application’s user and roles:

- Go to the Roles section and create the roles admin, kiemgmt and rest-all

- Go to the Users section and create the admin user. Set the password with value password in the credentials tab, unset the temporary switch.

- In the Users section navigate to the Role Mappings tab and assign the admin, kiemgmt and rest-all roles to the admin user

At this point a Keycloak server is running on the host, set up with a minimal configuration set. Let’s move to Business Central set up.

#### 5.3.4. Install and set up Business Central

For this tutorial let’s use a Wildfly as the application server for Business Central, as the jBPM installer does by default.

Let’s assume, after running the jBPM installer, the $JBPM_HOME as the root path for the Wildfly server where the application has been deployed.

##### 5.3.4.1. Install the KC adapter

In order to use the Keycloak’s authentication and authorization modules from the jBPM application, the Keycloak JBoss EAP/Wildfly Adapter must be installed on our server at $JBPM_HOME. Keycloak provides multiple adapters for different containers out of the box, if you are using another container or need to use another adapter, please take a look at the Securing Applications section from the Keycloak docs. Here are the steps to install and set up the adapter for Wildfly 11/10/9:

- Download the adapter from Keycloak Client Adapter for Wildfly 11/10/9

- Execute the following commands on your shell:

      cd $JBPM_HOME
      unzip keycloak-wildfly-adapter-dist-3.4.3.Final.zip // Install the KC client adapter

      cd $JBPM_HOME/bin
      ./standalone.sh -c standalone-full.xml // set up the KC client adapter.

      // ** Once server is up, open a new command line terminal and run:
      cd $JBPM_HOME/bin
      ./jboss-cli.sh -c --file=adapter-install.cli

##### 5.3.4.2. Configure the KC adapter

Once installed the KC adapter into Wildfly, next step is to configure the adapter in order to specify different settings such as the location for the authentication server, the realm to use and so on.

Keycloak provides two ways of configuring the adapter:

- Per WAR configuration

- Via Keycloak subsystem

In this example let’s use the second option, use the Keycloak subsystem, so our WAR is free from this kind of settings. If you want to use the per WAR approach, please take a look Required Per WAR Configuration.

Edit the configuration file $JBPM_HOME/standalone/configuration/standalone-full.xml and locate the subsystem configuration section. Add the following content:

    <subsystem xmlns="urn:jboss:domain:keycloak:1.1">
      <secure-deployment name="business-central-x.y.z.Final.war">
        <realm>demo</realm>
        <realm-public-key>MIIBIjANBgkqhkiG9w0BAQEFAAOCA...</realm-public-key>
        <auth-server-url>http://localhost:8180/auth</auth-server-url>
        <ssl-required>external</ssl-required>
        <resource>kie</resource>
        <enable-basic-auth>true</enable-basic-auth>
        <credential name="secret">925f9190-a7c1-4cfd-8a3c-004f9c73dae6</credential>
        <principal-attribute>preferred_username</principal-attribute>
      </secure-deployment>
    </subsystem>

If you have imported the example json files from this document in step 2, you can just use the same configuration as above by using your concrete deployment name. Otherwise please use your values for these configurations:

- Name for the secure deployment - Use your concrete application’s WAR file name

- Realm - Is the realm that the applications will use, in our example, the demo realm created in the previous step.

- Realm Public Key - Provide here the public key for the demo realm. It’s not mandatory, if it’s not specified, it will be retrieved from the server. Otherwise, you can find it in the Keycloak admin console → Realm settings (for demo realm) → Keys

- Authentication server URL - The URL for the Keycloak’s authentication server

- Resource - The name for the client created on step 2. In our example, use the value kie.

- Enable basic auth - For this example let’s enable Basic authentication mechanism as well, so clients can use both Token (Bearer) and Basic approaches to perform the requests.

- Credential - Use the password value for the kie client. You can find it in the Keycloak admin console → Clients → kie → Credentials tab → Copy the value for the secret.

For this example you have to take care about using your concrete values for secure-deployment name, realm-public-key and credential password.

| Ensure the following tag is NOT present in the Wildfly/EAP profile’s configuration file (eg: standalone.xml):
    <single-sign-on/>
It’s enabled by default in some server versions. If present, it must be removed/disabled in order to allow Keycloak to properly handle the clients.

##### 5.3.4.3. Run the environment

At this point a Keycloak server is up and running on the host, and the KC adapter is installed and configured for the jBPM application server. You can run the application using:

    $JBPM_HOME/bin/standalone.sh -c standalone-full.xml

You can navigate into the application once the server is up at:

     http://localhost:8080/business-central-x.y.z.Final

Use your Keycloak’s admin user credentials to login: admin/password.

#### 5.3.5. Securing Business Central remote services via Keycloak

Business Central provides different remote service endpoints that can be consumed by third party clients using the Knowledge Store REST API.

In order to authenticate those services through Keycloak, apply those modifications for the WEB-INF/web.xml file (app deployment descriptor) from jBPM’s WAR file:

- Constraint the remote services URL patterns as:

      <security-constraint>
        <web-resource-collection>
          <web-resource-name>remote-services</web-resource-name>
          <url-pattern>/rest/*</url-pattern>
          <url-pattern>/maven2/*</url-pattern>
          <url-pattern>/ws/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
          <role-name>rest-all</role-name>
        </auth-constraint>
      </security-constraint>

| The user that consumes the remote services must be member of role rest-all. As described in previous steps, the admin user in this example is already a member of the rest-all role.

#### 5.3.6. Securing Business Central’s file system services via Keycloak

In order to consume other remote services such as the file system ones (e.g. remote GIT), a specific Keycloak login module must be used for the application’s security domain in the $JBPM_HOME/standalone/configuration/standalone-full.xml file. By default Business Central uses the other security domain, so the resulting configuration on the $JBPM_HOME/standalone/configuration/standalone-full.xml should be such as:

    <security-domain name="other" cache-type="default">
        <authentication>
            <login-module code="org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule" flag="required">
                <!-- Parameter value can be a file system absolute path or a classpath (e.g. "classpath:/some-path/kie-git.json")-->
                <module-option name="keycloak-config-file" value="$JBPM_HOME/kie-git.json"/>
            </login-module>
        </authentication>
    </security-domain>

Note that:

- The login modules on the other security domain in the $JBPM_HOME/standalone/configuration/standalone-full.xml file must be REPLACED by the above given one.

- Replace $JBPM_HOME/kie-git.json by the path (on file system) or the classpath (e.g. classpath:/some-path/kie-git.json) for the json configuration file used for the remote services client. Please continue reading in order to create this Keycloak client and how to obtain this json file.

At this point, remote services that use JAAS for the authentication process, such as the file system ones (e.g. GIT), are secured by Keycloak using the client specified in the above json configuration file. So let’s create this client on Keycloak and generate the required JSON file:

- Navigate to the KC administration console and create a new client for the demo realm using kie-git as name.

- Enable Direct Access Grants Enabled option

- Disable Standard Flow Enabled option

- Use a confidential access type for this client. See below image as example:

- Go to the Installation tab in same kie-git client configuration screen and export using the Keycloak OIDC JSON type.

- Finally copy this generated JSON file into an accessible directory on the server’s file system or add it in the application’s classpath. Use this path value as the keycloak-config-file argument for the above configuration of the org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule login module.

- More information about Keycloak JAAS Login modules can be found Keycloak JAAS plugin.

At this point, the internal Git repositories can be cloned by all users authenticated via the Keycloak server:

    # Command example:
    git clone ssh://admin@localhost:8001/system

#### 5.3.7. Execution server

The KIE Execution Server provides a REST API that can be consumed for any third party clients. This section is about how to integrate the KIE Execution Server with the Keycloak SSO in order to delegate the third party clients identity management to the SSO server.

Consider the above environment running, so consider having:

- A Keycloak server running and listening on http://localhost:8180/auth

- A realm named demo with a client named kie for Business Central

- A Business Central running at http://localhost:8080/business-central-x.y.z.Final

Follow these steps in order to add an execution server into this environment:

- Create the client for the execution server on Keycloak

- Install set up and the Execution server (with the KC client adapter)

##### 5.3.7.1. Create the execution server’s client on Keycloak

As per each execution server is going to be deployed, you have to create a new client on the demo realm in Keycloak:

- Go to the KC admin console → Clients → New client

- Name: kie-execution-server

- Root URL: http://localhost:8280/

- Client protocol: openid-connect

- Access type: confidential (or public if you want so, but not recommended for production environments)

- Valid redirect URIs: /kie-server-x.y.z.Final/*

- Base URL: /kie-server-x.y.z.Final

In this example the admin user already created on previous steps is the one used for the client requests. So ensure that the admin user is a member of the role kie-server in order to use the execution server’s remote services. If the role does not exist, create it.

Note: This example considers that the execution server will be configured to run using a port offset of 200, so the HTTP port will be available at localhost:8280.

##### 5.3.7.2. Install and set up the KC adapter on the execution server

At this point, a client named kie-execution-server is ready on the KC server to use from the execution server.

Let’s install, set up and deploy the execution server:

- Install another Wildfly server to use for the execution server and the KC client adapter as well. You can follow above instructions for Business Central or follow the securing applications guide

- Edit the standalone-full.xml file from the Wildfly server’s configuration path and configure the KC subsystem adapter as:

      <secure-deployment name="kie-server-x.y.z.Final.war">
          <realm>demo</realm>
          <realm-public-key>MIGfMA0GCSqGSIb...</realm-public-key>
          <auth-server-url>http://localhost:8180/auth</auth-server-url>
          <ssl-required>external</ssl-required>
          <resource>kie-execution-server</resource>
          <enable-basic-auth>true</enable-basic-auth>
          <credential name="secret">e92ec68d-6177-4239-be05-28ef2f3460ff</credential>
          <principal-attribute>preferred_username</principal-attribute>
      </secure-deployment>

Consider your concrete environment settings if different from this example:

- Secure deployment name → use the name of the execution server war file being deployed

- Public key → Use the demo realm public key or leave it blank, the server will provide one if so

- Resource → This time, instead of the kie client used in the Business Central configuration, use the kie-execution-server client

- Enable basic auth → Up to you. You can enable Basic auth for third party service consumers

- Credential → Use the secret key for the kie-execution-server client. You can find it in the Credentials tab of the KC admin console

##### 5.3.7.3. Deploy and run the execution server

Just deploy the execution server in Wildfly using any of the available mechanisms. Run the execution server using this command:

    $EXEC_SERVER_HOME/bin/standalone.sh -c standalone-full.xml -Djboss.socket.binding.port-offset=200 -Dorg.kie.server.id=<ID> -Dorg.kie.server.user=<USER> -Dorg.kie.server.pwd=<PWD> -Dorg.kie.server.location=<LOCATION_URL>  -Dorg.kie.server.controller=<CONTROLLER_URL> -Dorg.kie.server.controller.user=<CONTROLLER_USER> -Dorg.kie.server.controller.pwd=<CONTOLLER_PASSWORD>

Example:

    $EXEC_SERVER_HOME/bin/standalone.sh -c standalone-full.xml -Djboss.socket.binding.port-offset=200 -Dorg.kie.server.id=kieserver1 -Dorg.kie.server.user=admin -Dorg.kie.server.pwd=password -Dorg.kie.server.location=http://localhost:8280/kie-server-x.y.z.Final/services/rest/server -Dorg.kie.server.controller=http://localhost:8080/business-central-x.y.z.Final/rest/controller -Dorg.kie.server.controller.user=admin -Dorg.kie.server.controller.pwd=password

| The users that will consume the execution server remote service endpoints must have the role kie-server assigned. So create and assign this role in the KC admin console for the users that will consume the execution server remote services.

Once up, you can check the server status as (considered using Basic authentication for this request, see next Consuming remote services for more information):

    curl http://admin:password@localhost:8280/kie-server-x.y.z.Final/services/rest/server/

#### 5.3.8. Consuming remote services

In order to use the different remote services provided by Business Central or by an Execution Server, your client must be authenticated on the KC server and have a valid token to perform the requests.

Remember that in order to use the remote services, the authenticated user must have assigned:

- The role rest-all for using the Business Central remote services

- The role kie-server for using the Execution Server remote services

Please ensure necessary roles are created and assigned to the users that will consume the remote services on the Keycloak admin console.

You have two options to consume the different remove service endpoints:

- Using basic authentication, if the application’s client supports it

- Using Bearer (token) based authentication

##### 5.3.8.1. Using basic authentication

If the KC client adapter configuration has the Basic authentication enabled, as proposed in this guide for both Business Central (step 3.2) and Execution Server, you can avoid the token grant/refresh calls and just call the services as the following examples.

Example for a Business Central remote repositories endpoint:

    curl http://admin:password@localhost:8080/business-central-x.y.z.Final/rest/repositories

Example to check the status for the Execution Server:

    curl http://admin:password@localhost:8280/kie-server-x.y.z.Final/services/rest/server/

##### 5.3.8.2. Using token-based authentication

First step is to create a new client on Keycloak that allows the third party remote service clients to obtain a token. It can be done as:

- Go to the KC admin console and create a new client using this configuration:

  - Client id: kie-remote

  - Client protocol: openid-connect

  - Access type: public

  - Valid redirect URIs: http://localhost/

- As we are going to manually obtain a token and invoke the service let’s increase the lifespan of tokens slightly. In production access tokens should have a relatively low timeout, ideally less than 5 minutes:

  - Go to the KC admin console

  - Click your Realm Settings

  - Click Tokens tab

  - Change the value for Access Token Lifespan to 15 minutes. That should give us plenty of time to obtain a token and invoke the service before it expires.

Once a public client for our remote clients has been created, you can now obtain the token by performing an HTTP request to the KC server’s tokens endpoint. Here is an example for command line:

    RESULT=`curl --data "grant_type=password&client_id=kie-remote&username=admin&password=password" http://localhost:8180/auth/realms/demo/protocol/openid-connect/token`

    TOKEN=`echo $RESULT | sed 's/.*access_token":"//g' | sed 's/".*//g'`

At this point, if you echo the $TOKEN it will output the token string obtained from the KC server, that can be now used to authorize further calls to the remote endpoints. For example, if you want to check the internal jBPM repositories:

    curl -H "Authorization: bearer $TOKEN" http://localhost:8080/business-central-x.y.z.Final/rest/repositories

#### 5.3.9. Keycloak and the Business Central’s security administration area

Business Central provides an administration area which provides user, group and role management features. For more information, see User and group management and Security management sections.

By default the application’s security management system points to the application’s server realm. For instance, in case of using the packaged distribution for Wildfly, it points to the Wildfly’s ApplicationRealm (properties based). It means the entities from the realm presented in the administration area are not the ones from the Keycloak realm that the application is using. There exist the following options in order to change this default behavior:

- Disable the user system administration

- Use the built-in Keycloak security management provider instead of the default one

In order to customize an existing jBPM application (WAR file) for using the Keycloak security management provider replace the content for WEB-INF/classes/security-management.properties by:

    org.uberfire.ext.security.management.api.userManagementServices=KCAdapterUserManagementService
    org.uberfire.ext.security.management.keycloak.authServer=<authz_server_url>
    # eg: org.uberfire.ext.security.management.keycloak.authServer=http://localhost:8180/auth

| The properties `org.uberfire.ext.security.management.api.userManagementServices` and `org.uberfire.ext.security.management.keycloak.authServer` can be set as system properties as well.

| The jar artifacts required in the steps above can be either downloaded from JBoss Nexus or either build from sources.

Once applying the above changes, the security administration area uses the access token present in the user’s session in order to authorize and manage the specific Keycloak realm data.

| In order to be able to manage Keycloak realms remotely, please ensure the user has the realm-management client role assigned

## 6. Business Central High Availability

### 6.1. VFS clustering

The VFS repositories (usually git repositories) stores all the assets (such as rules, decision tables, process definitions, forms, etc). If that VFS is located on each local server, then it must be kept in sync between all servers of a cluster.

Use Apache Zookeeper and Apache Helix to accomplish this. Zookeeper glues all the parts together. Helix is the cluster management component that registers all cluster details (nodes, resources and the cluster itself). Uberfire (on top of which Business Central is built) uses those 2 components to provide VFS clustering.

To create a VFS cluster:

1. Download Apache Zookeeper and Apache Helix.

2. Install both:

   1. Unzip Zookeeper into a directory (`$ZOOKEEPER_HOME`).

   2. In `$ZOOKEEPER_HOME`, copy `zoo_sample.conf` to `zoo.conf`

   3. Edit `zoo.conf`. Adjust the settings if needed. Usually only these 2 properties are relevant:

          # the directory where the snapshot is stored.
          dataDir=/tmp/zookeeper
          # the port at which the clients will connect
          clientPort=2181

   4. Unzip Helix into a directory (`$HELIX_HOME`).

3. Configure the cluster in Zookeeper:

   1. Go to its `bin` directory:

          $ cd $ZOOKEEPER_HOME/bin

   2. Start the Zookeeper server:

          $ sudo ./zkServer.sh start

      If the server fails to start, verify that the `dataDir` (as specified in `zoo.conf`) is accessible.

   3. To review Zookeeper’s activities, open `zookeeper.out`:

          $ cat $ZOOKEEPER_HOME/bin/zookeeper.out

4. Configure the cluster in Helix:

   1. Go to its `bin` directory:

          $ cd $HELIX_HOME/bin

   2. Create the cluster:

          $ ./helix-admin.sh --zkSvr localhost:2181 --addCluster kie-cluster

      The `zkSvr` value must match the used Zookeeper server. The cluster name (`kie-cluster`) can be changed as needed.

   3. Add nodes to the cluster:

          # Node 1
          $ ./helix-admin.sh --zkSvr localhost:2181 --addNode kie-cluster nodeOne:12345
          # Node 2
          $ ./helix-admin.sh --zkSvr localhost:2181 --addNode kie-cluster nodeTwo:12346
          ...

      Usually the number of nodes in a cluster equal the number of application servers in the cluster. The node names (`nodeOne:12345` , …​) can be changed as needed.

      | `nodeOne:12345` is the unique identifier of the node, which will be referenced later on when configuring application servers. It is not a host and port number, but instead it is used to uniquely identify the logical node.

   4. Add resources to the cluster:

          $ ./helix-admin.sh --zkSvr localhost:2181 --addResource kie-cluster vfs-repo 1 LeaderStandby AUTO_REBALANCE

      The resource name (`vfs-repo`) can be changed as needed.

   5. Rebalance the cluster to initialize it:

          $ ./helix-admin.sh --zkSvr localhost:2181 --rebalance kie-cluster vfs-repo 2

   6. Start the Helix controller to manage the cluster:

          $  ./run-helix-controller.sh --zkSvr localhost:2181 --cluster kie-cluster 2>&1 > /tmp/controller.log &

5. Configure the security domain correctly on the application server. For example on WildFly and JBoss EAP:

   1. Edit the file `$JBOSS_HOME/domain/configuration/domain.xml`.

      For simplicity sake, presume we use the default domain configuration which uses the profile `full` that defines two server nodes as part of `main-server-group`.

   2. Locate the profile `full` and add a new security domain by copying the other security domain already defined there by default:

          <security-domain name="kie-ide" cache-type="default">
              <authentication>
                   <login-module code="Remoting" flag="optional">
                       <module-option name="password-stacking" value="useFirstPass"/>
                   </login-module>
                   <login-module code="RealmDirect" flag="required">
                       <module-option name="password-stacking" value="useFirstPass"/>
                   </login-module>
              </authentication>
          </security-domain>

      | The security-domain name is a magic value.

6. Configure the system properties for the cluster on the application server. For example on WildFly and JBoss EAP:

   1. Edit the file `$JBOSS_HOME/domain/configuration/host.xml`.

   2. Locate the XML elements `server` that belong to the `main-server-group` and add the necessary system property.

      For example for nodeOne:

          <system-properties>
            <property name="jboss.node.name" value="nodeOne" boot-time="false"/>
            <property name="org.uberfire.nio.git.dir" value="/tmp/kie/nodeone" boot-time="false"/>
            <property name="org.uberfire.metadata.index.dir" value="/tmp/kie/nodeone" boot-time="false"/>
            <property name="org.uberfire.cluster.id" value="kie-cluster" boot-time="false"/>
            <property name="org.uberfire.cluster.zk" value="localhost:2181" boot-time="false"/>
            <property name="org.uberfire.cluster.local.id" value="nodeOne_12345" boot-time="false"/>
            <property name="org.uberfire.cluster.vfs.lock" value="vfs-repo" boot-time="false"/>
            <!-- If you're running both nodes on the same machine: -->
            <property name="org.uberfire.nio.git.daemon.port" value="9418" boot-time="false"/>
          </system-properties>

      And for nodeTwo:

          <system-properties>
            <property name="jboss.node.name" value="nodeTwo" boot-time="false"/>
            <property name="org.uberfire.nio.git.dir" value="/tmp/kie/nodetwo" boot-time="false"/>
            <property name="org.uberfire.metadata.index.dir" value="/tmp/kie/nodetwo" boot-time="false"/>
            <property name="org.uberfire.cluster.id" value="kie-cluster" boot-time="false"/>
            <property name="org.uberfire.cluster.zk" value="localhost:2181" boot-time="false"/>
            <property name="org.uberfire.cluster.local.id" value="nodeTwo_12346" boot-time="false"/>
            <property name="org.uberfire.cluster.vfs.lock" value="vfs-repo" boot-time="false"/>
            <!-- If you're running both nodes on the same machine: -->
            <property name="org.uberfire.nio.git.daemon.port" value="9419" boot-time="false"/>
          </system-properties>

      Make sure the cluster, node and resource names match those configured in Helix.

### 6.2. jBPM clustering

In addition to the information above, jBPM clustering requires additional configuration. See this blog post to configure the database etc correctly.

# OptaPlanner Execution Server

The KIE Server is a standalone execution server for rules, planning and workflows.

## 7. KIE Execution Server

### 7.1. Overview

KIE Server is a modular, standalone server component that can be used to instantiate and execute rules and processes. It exposes this functionality via REST, JMS and Java interfaces to client application. It also provides seamless integration with the Business Central.

At its core, KIE Server is a configurable web application packaged as a WAR file. Distributions are available for pure web containers (like Tomcat) and for JEE 6 and JEE 7 containers.

Most capabilities on the Kie Server are configurable, and based on the concepts of extensions. Each extension can be enabled/disabled independently, allowing the user to configure the server to its need.

The current version of the Kie Server ships with two default extensions:

- BRM: provides support for the execution of Business Rules using the Drools engine.

- BPM: provides support for the execution of Business Processes using the jBPM engine. It supports:

  - process execution

  - task execution

  - asynchronous job execution

Both extensions enabled by default, but can be disabled by setting the corresponding property (see configuration chapter for details).

This server was designed to have a low footprint, with minimal memory consumption, and therefore, to be easily deployable on a cloud environment. Each instance of this server can open and instantiate multiple Kie Containers which allows you to execute multiple services in parallel.

#### 7.1.1. Glossary

- Kie Server: execution server purely focusing on providing runtime environment for both rules and processes. These capabilities are provided by Kie Server Extensions. More capabilities can be added by further extensions (e.g. customer could add his own extensions in case of missing functionality that will then use infrastructure of the KIE Server). A Kie Server instance is a standalone Kie Server executing on a given application server/web container. A Kie Server instantiates and provides support for multiple Kie Containers.

- Kie Server Extension: a "plugin" for the Kie Server that adds capabilities to the server. The Kie Server ships with two default kie server extensions: BRM and BPM.

- Kie Container: an in-memory instantiation of a kjar, allowing for the instantiation and usage of its assets (domain models, processes, rules, etc). A Kie Server exposes Kie Containers through a standard API over transport protocols like REST and JMS.

- Controller: a server-backed REST endpoint that will be responsible for managing KIE Server instances. Such end point must provide following capabilities:

  - respond to connect requests

  - sync all registered containers on the corresponding Kie Server ID

  - respond to disconnect requests

- Kie Server state: currently known state of given Kie Server instance. This is a local storage (by default in file) that maintains the following information:

  - list of registered KIE Server controllers

  - list of known containers

  - kie server configuration

    The server state is persisted upon receival of events like: Kie Container created, Kie Container is disposed, KIE Server controller accepts registration of Kie Server instance, etc.

- Kie Server ID: an arbitrary assigned identifier to which configurations are assigned. At boot, each Kie Server Instance is assigned an ID, and that ID is matched to a configuration on the KIE Server controller. The Kie Server Instance fetches and uses that configuration to setup itself.

### 7.2. Installing the KIE Server

The KIE Server is distributed as a web application archive (WAR) file. The WAR file comes in three different packagings:

- webc - WAR for ordinary Web (Servlet) containers like Tomcat

- ee6 - WAR for JavaEE 6 containers like JBoss EAP 6.x

- ee7 - WAR for JavaEE 7 containers like WildFly 11.x

To install the KIE Execution Server and verify it is running, complete the following steps:

1. Deploy the WAR file into your web container.

2. Create a user with the role of `kie-server` on the container.

3. Test that you can access KIE Server by navigating to the endpoint in a browser window: `http://SERVER:PORT/CONTEXT/services/rest/server/`.

4. When prompted for user name/password, type in the user name and password that you created in step 2.

5. Once authenticated, you will see an XML response in the form of KIE Server status, similar to this:

   Example 1. Sample handshaking server response

       <response type="SUCCESS" msg="KIE Server info">
         <kie-server-info>
           <version>7.66.0.Final</version>
         </kie-server-info>
       </response>

#### 7.2.1. Installation details for different containers

##### 7.2.1.1. Tomcat 7.x/8.x

1. Download and unzip the Tomcat distribution. Let’s call the root of the distribution `TOMCAT_HOME`. This directory is named after the Tomcat version, so for example `apache-tomcat-7.0.55`.

2. Download kie-server- -webc.war and place it into `TOMCAT_HOME/webapps`.

3. Configure user(s) and role(s). Make sure that file `TOMCAT_HOME/conf/tomcat-users.xml` contains the following user name and role definition. You can of course choose different user name and password, just make sure that the user has role `kie-server`:

   Example 2. User name and role definition for Tomcat

       <role rolename="kie-server"/>
       <user username="serveruser" password="my.s3cr3t.pass" roles="kie-server"/>

4. Start the server by running `TOMCAT_HOME/bin/startup.[sh|bat]`. You can check out the Tomcat logs in `TOMCAT_HOME/logs` to see if the application deployed successfully. Please read the table above for the bootstrap switches that can be used to properly configure the instance. For instance:

       ./startup.sh -Dorg.kie.server.id=first-kie-server
                    -Dorg.kie.server.location=http://localhost:8080/kie-server/services/rest/server

5. Verify the server is running. Go to `http://SERVER:PORT/CONTEXT/services/rest/server/` and type the specified user name and password. You should see simple XML message with basic information about the server.

| You can not leverage the JMS interface when running with Tomcat, or any other Web container. The Web container version of the WAR contains only the REST interface.

##### 7.2.1.2. WildFly 11.x

1. Download and unzip the WildFly distribution. Let’s call the root of the distribution `WILDFLY_HOME`. This directory is named after the WildFly version, so for example `wildfly-14.0.1.Final`.

2. Download kie-server- -ee7.war and place it into `WILDFLY_HOME/standalone/deployments`.

3. Configure users and roles by executing the following command:

    $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity='kieserver'),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity='kieserver', clear={password='kieserver1!'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity='kieserver', name=role, value=['kie-server'])"

You can choose a different user name and password, just make sure that the user has role `kie-server`. . Start the server by running `WILDFLY_HOME/bin/standalone.[sh|bat] -c standalone-full.xml <bootstrap_switches>`. You can check out the standard output or WildFly logs in `WILDFLY_HOME/standalone/logs` to see if the application deployed successfully. Please read the table above for the bootstrap switches that can be used to properly configure the instance. For instance:

+

    ./standalone.sh  --server-config=standalone-full.xml
                     -Djboss.socket.binding.port-offset=150
                     -Dorg.kie.server.id=first-kie-server
                     -Dorg.kie.server.location=http://localhost:8230/kie-server/services/rest/server

1. Verify the server is running. Go to `http://SERVER:PORT/CONTEXT/services/rest/server/` and type the specified user name and password. You should see simple XML message with basic information about the server.

### 7.3. KIE Server system properties

KIE Server accepts the following system properties (bootstrap switches) to configure the behavior of the server:

Table 27. System properties for disabling KIE Server extensions
Property | Values | Default | Description
--- | --- | --- | ---
`org.drools.server.ext.disabled` | `true`, `false` | `false` | If set to `true`, disables the Business Rule Management (BRM) support (for example, rules support).
`org.optaplanner.server.ext.disabled` | `true`, `false` | `false` | If set to `true`, disables the Red Hat build of OptaPlanner support.
`org.kie.prometheus.server.ext.disabled` | `true`, `false` | `true` | If set to `true`, disables the Prometheus Server extension.
`org.kie.scenariosimulation.server.ext.disabled` | `true`, `false` | `true` | If set to `true`, disables the Test scenario Server extension.
`org.kie.dmn.server.ext.disabled` | `true`, `false` | `false` | If set to `true`, disables the KIE Server DMN support.
`org.kie.swagger.server.ext.disabled` | `true`, `false` | `false` | If set to `true`, disables the KIE Server swagger documentation support

| Some KIE Server controller properties listed in the following table are marked as required. Set these properties when you create or remove KIE Server containers in Business Central. If you use KIE Server separately without any interaction with Business Central, you do not need to set the required properties.

Table 28. System properties required for KIE Server controller
Property | Values | Default | Description
--- | --- | --- | ---
`org.kie.server.id` | String | N/A | An arbitrary ID to be assigned to the server. If a headless KIE Server controller is configured outside of Business Central, this is the ID under which the server connects to the headless KIE Server controller to fetch the KIE container configurations. If not provided, the ID is automatically generated.
`org.kie.server.user` | String | `kieserver` | The user name used to connect with KIE Server from the KIE Server controller, required when running in managed mode. Set this property in Business Central system properties. Set this property when using a KIE Server controller.
`org.kie.server.pwd` | String | `kieserver1!` | The password used to connect with KIE Server from the KIE Server controller, required when running in managed mode. Set this property in Business Central system properties. Set this property when using a KIE Server controller.
`org.kie.server.token` | String | N/A | A property that enables you to use token-based authentication between the KIE Server controller and KIE Server instead of the basic user name and password authentication. The KIE Server controller sends the token as a parameter in the request header. The server requires long-lived access tokens because the tokens are not refreshed.
`org.kie.server.location` | URL | N/A | The URL of the KIE Server instance used by the KIE Server controller to call back on this server, for example, `http://localhost:8230/kie-server/services/rest/server`. Setting this property is required when using a KIE Server controller.
`org.kie.server.controller` | Comma-separated list | N/A | A comma-separated list of URLs to the KIE Server controller REST endpoints, for example, `http://localhost:8080/business-central/rest/controller`. Setting this property is required when using a KIE Server controller.
`org.kie.server.controller.user` | String | `kieserver` | The user name to connect to the KIE Server controller REST API. Setting this property is required when using a KIE Server controller.
`org.kie.server.controller.pwd` | String | `kieserver1!` | The password to connect to the KIE Server controller REST API. Setting this property is required when using a KIE Server controller.
`org.kie.server.controller.token` | String | N/A | A property that enables you to use token-based authentication between KIE Server and the KIE Server controller instead of the basic user name and password authentication. The server sends the token as a parameter in the request header. The server requires long-lived access tokens because the tokens are not refreshed.
`org.kie.server.controller.connect` | Long | `10000` | The waiting time in milliseconds between repeated attempts to connect KIE Server to the KIE Server controller when the server starts.

Table 29. System properties for loading keystore
Property | Values | Default | Description
--- | --- | --- | ---
`kie.keystore.keyStoreURL` | URL | N/A | The URL is used to load a Java Cryptography Extension KeyStore (JCEKS). For example, `file:///home/kie/keystores/keystore.jceks`.
`kie.keystore.keyStorePwd` | String | N/A | The password is used for the JCEKS.
`kie.keystore.key.server.alias` | String | N/A | The alias name of the key for REST services where the password is stored.
`kie.keystore.key.server.pwd` | String | N/A | The password of an alias for REST services.
`kie.keystore.key.ctrl.alias` | String | N/A | The alias of the key for default REST KIE Server controller.
`kie.keystore.key.ctrl.pwd` | String | N/A | The password of an alias for default REST KIE Server controller.

Table 30. System properties for retrying committing transactions
Property | Values | Default | Description
--- | --- | --- | ---
`org.kie.optlock.retries` | Integer | 5 | This property describes how many times the process engine retries a transaction before failing permanently.
`org.kie.optlock.delay` | Integer | 50 | The delay time before the first retry, in milliseconds.
`org.kie.optlock.delayFactor` | Integer | 4 | The multiplier for increasing the delay time for each subsequent retry. With the default values, the process engine waits 50 milliseconds before the first retry, 200 milliseconds before the second retry, 800 milliseconds before the third retry, and so on.

Table 31. Other system properties
Property | Values | Default | Description
--- | --- | --- | ---
`kie.maven.settings.custom` | Path | N/A | The location of a custom `settings.xml` file for Maven configuration.
`kie.server.jms.queues.response` | String | `queue/KIE.SERVER.RESPONSE` | The response queue JNDI name for JMS.
`org.drools.server.filter.classes` | `true`, `false` | `false` | When set to `true`, the Drools KIE Server extension accepts custom classes annotated by the `XmlRootElement` or `Remotable` annotations only.
`org.kie.server.domain` | String | N/A | The JAAS `LoginContext` domain used to authenticate users when using JMS.
`org.kie.server.repo` | Path | `.` | The location where KIE Server state files are stored.
`org.kie.server.sync.deploy` | `true`, `false` | `false` | A property that instructs KIE Server to hold the deployment until the KIE Server controller provides the container deployment configuration. This property only affects servers running in managed mode. The following options are available: * `false`: The connection to the KIE Server controller is asynchronous. The application starts, connects to the KIE Server controller, and once successful, deploys the containers. The application accepts requests even before the containers are available. * `true`: The deployment of the server application joins the KIE Server controller connection thread with the main deployment and awaits its completion. This option can lead to a potential deadlock in case more applications are on the same server. Use only one application on one server instance.
`org.kie.server.startup.strategy` | `ControllerBasedStartupStrategy`, `LocalContainersStartupStrategy` | `ControllerBasedStartupStrategy` | The Startup strategy of KIE Server used to control the KIE containers that are deployed and the order in which they are deployed.
`org.kie.server.mgmt.api.disabled` | `true`, `false` | `false` | When set to `true`, disables KIE Server management API.
`org.kie.server.xstream.enabled.packages` | Java packages like `org.kie.example`. You can also specify wildcard expressions like `org.kie.example.*`. | N/A | A property that specifies additional packages to allowlist for marshalling using XStream.
`org.kie.store.services.class` | String | `org.drools.persistence.jpa.KnowledgeStoreServiceImpl` | Fully qualified name of the class that implements `KieStoreServices` that are responsible for bootstrapping KieSession instances.
`org.kie.server.strict.id.format` | `true`, `false` | `false` | While using JSON marshalling, if the property is set to `true`, it will always return a response in the proper JSON format. For example, if the original response contains only a single number, then the response is wrapped in a JSON format. For example, {"value" : 1}.
`org.kie.server.json.customObjectDeserializerCNFEBehavior` | `IGNORE`, `WARN`, `EXCEPTION` | `IGNORE` | While using JSON unmarshalling, when a class in a payload is not found, the behavior can be changed using this property as follows: If the property is set to `IGNORE`, the payload is converted to a HashMap If the property is set to `WARN`, the payload is converted to a HashMap and a warning is logged If the property is set to `EXCEPTION`, KIE Server throws an exception
`org.kie.server.strict.jaxb.format` | `true`, `false` | `false` | When the value of this property is set to `true`, KIE Server validates the data type of the data in the REST API payload. For example, if a data field has the number data type and contains something other than a number, you will receive an error.

### 7.4. KIE Server capabilities and extensions

The capabilities in KIE Server are determined by plug-in extensions that you can enable, disable, or further extend to meet your business needs. KIE Server supports the following default capabilities and extensions:

Table 32. KIE Server capabilities and extensions
Capability name | Extension name | Description
--- | --- | ---
`KieServer` | `KieServer` | Provides the core capabilities of KIE Server, such as creating and disposing KIE containers on your server instance
`BRM` | `Drools` | Provides the Business Rule Management (BRM) capabilities, such as inserting facts and executing business rules
`BRP` | `OptaPlanner` | Provides the Business Resource Planning (BRP) capabilities, such as implementing solvers
`DMN` | `DMN` | Provides the Decision Model and Notation (DMN) capabilities, such as managing DMN data types and executing DMN models
`Swagger` | `Swagger` | Provides the Swagger web-interface capabilities for interacting with the KIE Server REST API

To view the supported extensions of a running KIE Server instance, send a `GET` request to the following REST API endpoint and review the XML or JSON server response:

Base URL for GET request for KIE Server information

    http://SERVER:PORT/kie-server/services/rest/server

Example JSON response with KIE Server information

    {
      "type": "SUCCESS",
      "msg": "Kie Server info",
      "result": {
        "kie-server-info": {
          "id": "test-kie-server",
          "version": "7.59.0.20190818-050814",
          "name": "test-kie-server",
          "location": "http://localhost:8080/kie-server/services/rest/server",
          "capabilities": [
            "KieServer",
            "BRM",
            "BRP",
            "DMN",
            "Swagger"
          ],
          "messages": [
            {
              "severity": "INFO",
              "timestamp": {
                "java.util.Date": 1566169865791
              },
              "content": [
                "Server KieServerInfo{serverId='test-kie-server', version='7.59.0.20190818-050814', name='test-kie-server', location='http:/localhost:8080/kie-server/services/rest/server', capabilities=[KieServer, BRM, BRP, DMN, Swagger]', messages=null', mode=DEVELOPMENT}started successfully at Sun Aug 18 23:11:05 UTC 2019"
              ]
            }
          ],
          "mode": "DEVELOPMENT"
        }
      }
    }

To enable or disable KIE Server extensions, configure the related `*.server.ext.disabled` KIE Server system property. For example, to disable the `BRM` capability, set the system property `org.drools.server.ext.disabled=true`. For all KIE Server system properties, see KIE Server system properties.

By default, KIE Server extensions are exposed through REST or JMS data transports and use predefined client APIs. You can extend existing KIE Server capabilities with additional REST endpoints, extend supported transport methods beyond REST or JMS, or extend functionality in the KIE Server client.

This flexibility in KIE Server functionality enables you to adapt your KIE Server instances to your business needs, instead of adapting your business needs to the default KIE Server capabilities.

#### 7.4.1. Extending an existing KIE Server capability with a custom REST API endpoint

The KIE Server REST API enables you to interact with your KIE containers and business assets (such as business rules, processes, and solvers) in OptaPlanner without using the Business Central user interface. The available REST endpoints are determined by the capabilities enabled in your KIE Server system properties (for example, `org.drools.server.ext.disabled=false` for the `BRM` capability). You can extend an existing KIE Server capability with a custom REST API endpoint to further adapt the KIE Server REST API to your business needs.

As an example, this procedure extends the `Drools` KIE Server extension (for the `BRM` capability) with the following custom REST API endpoint:

Example custom REST API endpoint

    /server/containers/instances/{containerId}/ksession/{ksessionId}

This example custom endpoint accepts a list of facts to be inserted into the working memory of the Drools engine, automatically executes all rules, and retrieves all objects from the KIE session in the specified KIE container.

Procedure

1. Create an empty Maven project and define the following packaging type and dependencies in the `pom.xml` file for the project:

   Example pom.xml file in the sample project

       <packaging>jar</packaging>

       <properties>
         <version.org.kie>7.59.0.Final</version.org.kie>
       </properties>

       <dependencies>
         <dependency>
           <groupId>org.kie</groupId>
           <artifactId>kie-api</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie</groupId>
           <artifactId>kie-internal</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-api</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-services-common</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-services-drools</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-rest-common</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.drools</groupId>
           <artifactId>drools-core</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.drools</groupId>
           <artifactId>drools-compiler</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-api</artifactId>
           <version>1.7.25</version>
         </dependency>
       </dependencies>

2. Implement the `org.kie.server.services.api.KieServerApplicationComponentsService` interface in a Java class in your project, as shown in the following example:

   Sample implementation of the `KieServerApplicationComponentsService` interface

       public class CusomtDroolsKieServerApplicationComponentsService implements KieServerApplicationComponentsService {  (1)

           private static final String OWNER_EXTENSION = "Drools";  (2)

           public Collection<Object> getAppComponents(String extension, SupportedTransports type, Object... services) {  (3)
               // Do not accept calls from extensions other than the owner extension:
               if ( !OWNER_EXTENSION.equals(extension) ) {
                   return Collections.emptyList();
               }

               RulesExecutionService rulesExecutionService = null;  (4)
               KieServerRegistry context = null;

               for( Object object : services ) {
                   if( RulesExecutionService.class.isAssignableFrom(object.getClass()) ) {
                       rulesExecutionService = (RulesExecutionService) object;
                       continue;
                   } else if( KieServerRegistry.class.isAssignableFrom(object.getClass()) ) {
                       context = (KieServerRegistry) object;
                       continue;
                   }
               }

               List<Object> components = new ArrayList<Object>(1);
               if( SupportedTransports.REST.equals(type) ) {
                   components.add(new CustomResource(rulesExecutionService, context));  (5)
               }

               return components;
           }

       }

   1 | Delivers REST endpoints to the KIE Server infrastructure that is deployed when the application starts.
   2 | Specifies the extension that you are extending, such as the `Drools` extension in this example.
   3 | Returns all resources that the REST container must deploy. Each extension that is enabled in your KIE Server instance calls the `getAppComponents` method, so the `if ( !OWNER_EXTENSION.equals(extension) )` call returns an empty collection for any extensions other than the specified `OWNER_EXTENSION` extension.
   4 | Lists the services from the specified extension that you want to use, such as the `RulesExecutionService` and `KieServerRegistry` services from the `Drools` extension in this example.
   5 | Specifies the transport type for the extension, either `REST` or `JMS` (`REST` in this example), and the `CustomResource` class that returns the resource as part of the `components` list.

3. Implement the `CustomResource` class that KIE Server can use to provide the additional functionality for the new REST resource, as shown in the following example:

   Sample implementation of the `CustomResource` class

       // Custom base endpoint:
       @Path("server/containers/instances/{containerId}/ksession")
       public class CustomResource {

           private static final Logger logger = LoggerFactory.getLogger(CustomResource.class);

           private KieCommands commandsFactory = KieServices.Factory.get().getCommands();

           private RulesExecutionService rulesExecutionService;
           private KieServerRegistry registry;

           public CustomResource() {

           }

           public CustomResource(RulesExecutionService rulesExecutionService, KieServerRegistry registry) {
               this.rulesExecutionService = rulesExecutionService;
               this.registry = registry;
           }

           // Supported HTTP method, path parameters, and data formats:
           @POST
           @Path("/{ksessionId}")
           @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
           @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
           public Response insertFireReturn(@Context HttpHeaders headers,
                   @PathParam("containerId") String id,
                   @PathParam("ksessionId") String ksessionId,
                   String cmdPayload) {

               Variant v = getVariant(headers);
               String contentType = getContentType(headers);

               // Marshalling behavior and supported actions:
               MarshallingFormat format = MarshallingFormat.fromType(contentType);
               if (format == null) {
                   format = MarshallingFormat.valueOf(contentType);
               }
               try {
                   KieContainerInstance kci = registry.getContainer(id);

                   Marshaller marshaller = kci.getMarshaller(format);

                   List<?> listOfFacts = marshaller.unmarshall(cmdPayload, List.class);

                   List<Command<?>> commands = new ArrayList<Command<?>>();
                   BatchExecutionCommand executionCommand = commandsFactory.newBatchExecution(commands, ksessionId);

                   for (Object fact : listOfFacts) {
                       commands.add(commandsFactory.newInsert(fact, fact.toString()));
                   }
                   commands.add(commandsFactory.newFireAllRules());
                   commands.add(commandsFactory.newGetObjects());

                   ExecutionResults results = rulesExecutionService.call(kci, executionCommand);

                   String result = marshaller.marshall(results);

                   logger.debug("Returning OK response with content '{}'", result);
                   return createResponse(result, v, Response.Status.OK);
               } catch (Exception e) {
                   // If marshalling fails, return the `call-container` response to maintain backward compatibility:
                   String response = "Execution failed with error : " + e.getMessage();
                   logger.debug("Returning Failure response with content '{}'", response);
                   return createResponse(response, v, Response.Status.INTERNAL_SERVER_ERROR);
               }

           }
       }

   In this example, the `CustomResource` class for the custom endpoint specifies the following data and behavior:

   - Uses the base endpoint `server/containers/instances/{containerId}/ksession`

   - Uses `POST` HTTP method

   - Expects the following data to be given in REST requests:

     - The `containerId` as a path argument

     - The `ksessionId` as a path argument

     - List of facts as a message payload

   - Supports all KIE Server data formats:

     - XML (JAXB, XStream)

     - JSON

   - Unmarshals the payload into a `List<?>` collection and, for each item in the list, creates an `InsertCommand` instance followed by `FireAllRules` and `GetObject` commands.

   - Adds all commands to the `BatchExecutionCommand` instance that calls to the Drools engine.

4. To make the new endpoint discoverable for KIE Server, create a `META-INF/services/org.kie.server.services.api.KieServerApplicationComponentsService` file in your Maven project and add the fully qualified class name of the `KieServerApplicationComponentsService` implementation class within the file. For this example, the file contains the single line `org.kie.server.ext.drools.rest.CusomtDroolsKieServerApplicationComponentsService`.

5. Build your project and copy the resulting JAR file into the `~/kie-server.war/WEB-INF/lib` directory of your project.

6. Start KIE Server and deploy the built project to the running KIE Server. You can deploy the project using either the Business Central interface or the KIE Server REST API (a `PUT` request to `http://SERVER:PORT/kie-server/services/rest/server/containers/{containerId}`).

   After your project is deployed on a running KIE Server, you can start interacting with your new REST endpoint.

   For this example, you can use the following information to invoke the new endpoint:

   - Example request URL: `http://localhost:8080/kie-server/services/rest/server/containers/instances/demo/ksession/defaultKieSession`

   - HTTP method: `POST`

   - HTTP headers:

     - `Content-Type: application/json`

     - `Accept: application/json`

   - Example message payload:

         [
           {
             "org.jbpm.test.Person": {
               "name": "john",
               "age": 25
             }
           },
           {
             "org.jbpm.test.Person": {
               "name": "mary",
               "age": 22
             }
           }
         ]

   - Example server response: `200` (success)

   - Example server log output:

         13:37:20,347 INFO  [stdout] (default task-24) Hello mary
         13:37:20,348 INFO  [stdout] (default task-24) Hello john

#### 7.4.2. Extending KIE Server to use a custom data transport

By default, KIE Server extensions are exposed through REST or JMS data transports. You can extend KIE Server to support a custom data transport to adapt KIE Server transport protocols to your business needs.

As an example, this procedure adds a custom data transport to KIE Server that uses the `Drools` extension and that is based on Apache MINA, an open-source Java network-application framework. The example custom MINA transport exchanges string-based data that relies on existing marshalling operations and supports only JSON format.

Procedure

1. Create an empty Maven project and define the following packaging type and dependencies in the `pom.xml` file for the project:

   Example pom.xml file in the sample project

       <packaging>jar</packaging>

       <properties>
         <version.org.kie>7.59.0.Final</version.org.kie>
       </properties>

       <dependencies>
         <dependency>
           <groupId>org.kie</groupId>
           <artifactId>kie-api</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie</groupId>
           <artifactId>kie-internal</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-api</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-services-common</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-services-drools</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.drools</groupId>
           <artifactId>drools-core</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.drools</groupId>
           <artifactId>drools-compiler</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.slf4j</groupId>
           <artifactId>slf4j-api</artifactId>
           <version>1.7.25</version>
         </dependency>
         <dependency>
           <groupId>org.apache.mina</groupId>
           <artifactId>mina-core</artifactId>
           <version>2.1.3</version>
         </dependency>
       </dependencies>

2. Implement the `org.kie.server.services.api.KieServerExtension` interface in a Java class in your project, as shown in the following example:

   Sample implementation of the `KieServerExtension` interface

       public class MinaDroolsKieServerExtension implements KieServerExtension {

           private static final Logger logger = LoggerFactory.getLogger(MinaDroolsKieServerExtension.class);

           public static final String EXTENSION_NAME = "Drools-Mina";

           private static final Boolean disabled = Boolean.parseBoolean(System.getProperty("org.kie.server.drools-mina.ext.disabled", "false"));
           private static final String MINA_HOST = System.getProperty("org.kie.server.drools-mina.ext.port", "localhost");
           private static final int MINA_PORT = Integer.parseInt(System.getProperty("org.kie.server.drools-mina.ext.port", "9123"));

           // Taken from dependency on the `Drools` extension:
           private KieContainerCommandService batchCommandService;

           // Specific to MINA:
           private IoAcceptor acceptor;

           public boolean isActive() {
               return disabled == false;
           }

           public void init(KieServerImpl kieServer, KieServerRegistry registry) {

               KieServerExtension droolsExtension = registry.getServerExtension("Drools");
               if (droolsExtension == null) {
                   logger.warn("No Drools extension available, quitting...");
                   return;
               }

               List<Object> droolsServices = droolsExtension.getServices();
               for( Object object : droolsServices ) {
                   // If the given service is null (not configured), continue to the next service:
                   if (object == null) {
                       continue;
                   }
                   if( KieContainerCommandService.class.isAssignableFrom(object.getClass()) ) {
                       batchCommandService = (KieContainerCommandService) object;
                       continue;
                   }
               }
               if (batchCommandService != null) {
                   acceptor = new NioSocketAcceptor();
                   acceptor.getFilterChain().addLast( "codec", new ProtocolCodecFilter( new TextLineCodecFactory( Charset.forName( "UTF-8" ))));

                   acceptor.setHandler( new TextBasedIoHandlerAdapter(batchCommandService) );
                   acceptor.getSessionConfig().setReadBufferSize( 2048 );
                   acceptor.getSessionConfig().setIdleTime( IdleStatus.BOTH_IDLE, 10 );
                   try {
                       acceptor.bind( new InetSocketAddress(MINA_HOST, MINA_PORT) );

                       logger.info("{} -- Mina server started at {} and port {}", toString(), MINA_HOST, MINA_PORT);
                   } catch (IOException e) {
                       logger.error("Unable to start Mina acceptor due to {}", e.getMessage(), e);
                   }

               }
           }

           public void destroy(KieServerImpl kieServer, KieServerRegistry registry) {
               if (acceptor != null) {
                   acceptor.dispose();
                   acceptor = null;
               }
               logger.info("{} -- Mina server stopped", toString());
           }

           public void createContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
               // Empty, already handled by the `Drools` extension

           }

           public void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters) {
             // Empty, already handled by the `Drools` extension

           }

           public List<Object> getAppComponents(SupportedTransports type) {
               // Nothing for supported transports (REST or JMS)
               return Collections.emptyList();
           }

           public <T> T getAppComponents(Class<T> serviceType) {

               return null;
           }

           public String getImplementedCapability() {
               return "BRM-Mina";
           }

           public List<Object> getServices() {
               return Collections.emptyList();
           }

           public String getExtensionName() {
               return EXTENSION_NAME;
           }

           public Integer getStartOrder() {
               return 20;
           }

           @Override
           public String toString() {
               return EXTENSION_NAME + " KIE Server extension";
           }
       }

   The `KieServerExtension` interface is the main extension interface that KIE Server can use to provide the additional functionality for the new MINA transport. The interface consists of the following components:

   Overview of the `KieServerExtension` interface

       public interface KieServerExtension {

           boolean isActive();

           void init(KieServerImpl kieServer, KieServerRegistry registry);

           void destroy(KieServerImpl kieServer, KieServerRegistry registry);

           void createContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters);

           void disposeContainer(String id, KieContainerInstance kieContainerInstance, Map<String, Object> parameters);

           List<Object> getAppComponents(SupportedTransports type);

           <T> T getAppComponents(Class<T> serviceType);

           String getImplementedCapability();  (1)

           List<Object> getServices();

           String getExtensionName();  (2)

           Integer getStartOrder();  (3)
       }

   1 | Specifies the capability that is covered by this extension. The capability must be unique within KIE Server.
   2 | Defines a human-readable name for the extension.
   3 | Determines when the specified extension should be started. For extensions that have dependencies on other extensions, this setting must not conflict with the parent setting. For example, in this case, this custom extension depends on the `Drools` extension, which has `StartOrder` set to `0`, so this custom add-on extension must be greater than `0` (set to `20` in the sample implementation).

   In the previous `MinaDroolsKieServerExtension` sample implementation of this interface, the `init` method is the main element for collecting services from the `Drools` extension and for bootstrapping the MINA server. All other methods in the `KieServerExtension` interface can remain with the standard implementation to fulfill interface requirements.

   The `TextBasedIoHandlerAdapter` class is the handler on the MINA server that reacts to incoming requests.

3. Implement the `TextBasedIoHandlerAdapter` handler for the MINA server, as shown in the following example:

   Sample implementation of the `TextBasedIoHandlerAdapter` handler

       public class TextBasedIoHandlerAdapter extends IoHandlerAdapter {

           private static final Logger logger = LoggerFactory.getLogger(TextBasedIoHandlerAdapter.class);

           private KieContainerCommandService batchCommandService;

           public TextBasedIoHandlerAdapter(KieContainerCommandService batchCommandService) {
               this.batchCommandService = batchCommandService;
           }

           @Override
           public void messageReceived( IoSession session, Object message ) throws Exception {
               String completeMessage = message.toString();
               logger.debug("Received message '{}'", completeMessage);
               if( completeMessage.trim().equalsIgnoreCase("quit") || completeMessage.trim().equalsIgnoreCase("exit") ) {
                   session.close(false);
                   return;
               }

               String[] elements = completeMessage.split("\\|");
               logger.debug("Container id {}", elements[0]);
               try {
                   ServiceResponse<String> result = batchCommandService.callContainer(elements[0], elements[1], MarshallingFormat.JSON, null);

                   if (result.getType().equals(ServiceResponse.ResponseType.SUCCESS)) {
                       session.write(result.getResult());
                       logger.debug("Successful message written with content '{}'", result.getResult());
                   } else {
                       session.write(result.getMsg());
                       logger.debug("Failure message written with content '{}'", result.getMsg());
                   }
               } catch (Exception e) {

               }
           }
       }

   In this example, the handler class receives text messages and executes them in the `Drools` service.

   Consider the following handler requirements and behavior when you use the `TextBasedIoHandlerAdapter` handler implementation:

   - Anything that you submit to the handler must be a single line because each incoming transport request is a single line.

   - You must pass a KIE container ID in this single line so that the handler expects the format `containerID|payload`.

   - You can set a response in the way that it is produced by the marshaller. The response can be multiple lines.

   - The handler supports a stream mode that enables you to send commands without disconnecting from a KIE Server session. To end a KIE Server session in stream mode, send either an `exit` or `quit` command to the server.

4. To make the new data transport discoverable for KIE Server, create a `META-INF/services/org.kie.server.services.api.KieServerExtension` file in your Maven project and add the fully qualified class name of the `KieServerExtension` implementation class within the file. For this example, the file contains the single line `org.kie.server.ext.mina.MinaDroolsKieServerExtension`.

5. Build your project and copy the resulting JAR file and the `mina-core-2.0.9.jar` file (which the extension depends on in this example) into the `~/kie-server.war/WEB-INF/lib` directory of your project.

6. Start the KIE Server and deploy the built project to the running KIE Server. You can deploy the project using either the Business Central interface or the KIE Server REST API (a `PUT` request to `http://SERVER:PORT/kie-server/services/rest/server/containers/{containerId}`).

   After your project is deployed on a running KIE Server, you can view the status of the new data transport in your KIE Server log and start using your new data transport:

   New data transport in the server log

       Drools-Mina KIE Server extension -- Mina server started at localhost and port 9123
       Drools-Mina KIE Server extension has been successfully registered as server extension

   For this example, you can use Telnet to interact with the new MINA-based data transport in KIE Server:

   Starting Telnet and connecting to KIE Server on port 9123 in a command terminal

       telnet 127.0.0.1 9123

   Example interactions with KIE Server in a command terminal

       Trying 127.0.0.1...
       Connected to localhost.
       Escape character is '^]'.

       # Request body:
       demo|{"lookup":"defaultKieSession","commands":[{"insert":{"object":{"org.jbpm.test.Person":{"name":"john","age":25}}}},{"fire-all-rules":""}]}

       # Server response:
       {
         "results" : [ {
           "key" : "",
           "value" : 1
         } ],
         "facts" : [ ]
       }

       demo|{"lookup":"defaultKieSession","commands":[{"insert":{"object":{"org.jbpm.test.Person":{"name":"mary","age":22}}}},{"fire-all-rules":""}]}
       {
         "results" : [ {
           "key" : "",
           "value" : 1
         } ],
         "facts" : [ ]
       }

       demo|{"lookup":"defaultKieSession","commands":[{"insert":{"object":{"org.jbpm.test.Person":{"name":"james","age":25}}}},{"fire-all-rules":""}]}
       {
         "results" : [ {
           "key" : "",
           "value" : 1
         } ],
         "facts" : [ ]
       }
       exit
       Connection closed by foreign host.

   Example server log output

       16:33:40,206 INFO  [stdout] (NioProcessor-2) Hello john
       16:34:03,877 INFO  [stdout] (NioProcessor-2) Hello mary
       16:34:19,800 INFO  [stdout] (NioProcessor-2) Hello james

#### 7.4.3. Extending the KIE Server client with a custom client API

KIE Server uses predefined client APIs that you can interact with to use KIE Server services. You can extend the KIE Server client with a custom client API to adapt KIE Server services to your business needs.

As an example, this procedure adds a custom client API to KIE Server to accommodate a custom data transport (configured previously for this scenario) that is based on Apache MINA, an open-source Java network-application framework.

Procedure

1. Create an empty Maven project and define the following packaging type and dependencies in the `pom.xml` file for the project:

   Example pom.xml file in the sample project

       <packaging>jar</packaging>

       <properties>
          <version.org.kie>7.59.0.Final</version.org.kie>
        </properties>

        <dependencies>
          <dependency>
            <groupId>org.kie.server</groupId>
            <artifactId>kie-server-api</artifactId>
            <version>${version.org.kie}</version>
          </dependency>
          <dependency>
             <groupId>org.kie.server</groupId>
             <artifactId>kie-server-client</artifactId>
             <version>${version.org.kie}</version>
           </dependency>
          <dependency>
            <groupId>org.drools</groupId>
            <artifactId>drools-compiler</artifactId>
            <version>${version.org.kie}</version>
          </dependency>
        </dependencies>

2. Implement the relevant `ServicesClient` interface in a Java class in your project, as shown in the following example:

   Sample `RulesMinaServicesClient` interface

       public interface RulesMinaServicesClient extends RuleServicesClient {

       }

   A specific interface is required because you must register client implementations based on the interface, and you can have only one implementation for a given interface.

   For this example, the custom MINA-based data transport uses the `Drools` extension, so this example `RulesMinaServicesClient` interface extends the existing `RuleServicesClient` client API from the `Drools` extension.

3. Implement the `RulesMinaServicesClient` interface that KIE Server can use to provide the additional client functionality for the new MINA transport, as shown in the following example:

   Sample implementation of the `RulesMinaServicesClient` interface

       public class RulesMinaServicesClientImpl implements RulesMinaServicesClient {

           private String host;
           private Integer port;

           private Marshaller marshaller;

           public RulesMinaServicesClientImpl(KieServicesConfiguration configuration, ClassLoader classloader) {
               String[] serverDetails = configuration.getServerUrl().split(":");

               this.host = serverDetails[0];
               this.port = Integer.parseInt(serverDetails[1]);

               this.marshaller = MarshallerFactory.getMarshaller(configuration.getExtraJaxbClasses(), MarshallingFormat.JSON, classloader);
           }

           public ServiceResponse<String> executeCommands(String id, String payload) {

               try {
                   String response = sendReceive(id, payload);
                   if (response.startsWith("{")) {
                       return new ServiceResponse<String>(ResponseType.SUCCESS, null, response);
                   } else {
                       return new ServiceResponse<String>(ResponseType.FAILURE, response);
                   }
               } catch (Exception e) {
                   throw new KieServicesException("Unable to send request to KIE Server", e);
               }
           }

           public ServiceResponse<String> executeCommands(String id, Command<?> cmd) {
               try {
                   String response = sendReceive(id, marshaller.marshall(cmd));
                   if (response.startsWith("{")) {
                       return new ServiceResponse<String>(ResponseType.SUCCESS, null, response);
                   } else {
                       return new ServiceResponse<String>(ResponseType.FAILURE, response);
                   }
               } catch (Exception e) {
                   throw new KieServicesException("Unable to send request to KIE Server", e);
               }
           }

           protected String sendReceive(String containerId, String content) throws Exception {

               // Flatten the content to be single line:
               content = content.replaceAll("\\n", "");

               Socket minaSocket = null;
               PrintWriter out = null;
               BufferedReader in = null;

               StringBuffer data = new StringBuffer();
               try {
                   minaSocket = new Socket(host, port);
                   out = new PrintWriter(minaSocket.getOutputStream(), true);
                   in = new BufferedReader(new InputStreamReader(minaSocket.getInputStream()));

                   // Prepare and send data:
                   out.println(containerId + "|" + content);
                   // Wait for the first line:
                   data.append(in.readLine());
                   // Continue as long as data is available:
                   while (in.ready()) {
                       data.append(in.readLine());
                   }

                   return data.toString();
               } finally {
                   out.close();
                   in.close();
                   minaSocket.close();
               }
           }
       }

   This example implementation specifies the following data and behavior:

   - Uses socket-based communication for simplicity

   - Relies on default configurations from the KIE Server client and uses `ServerUrl` for providing the host and port of the MINA server

   - Specifies JSON as the marshalling format

   - Requires received messages to be JSON objects that start with an open bracket `{`

   - Uses direct socket communication with a blocking API while waiting for the first line of the response and then reads all lines that are available

   - Does not use stream mode and therefore disconnects the KIE Server session after invoking a command

4. Implement the `org.kie.server.client.helper.KieServicesClientBuilder` interface in a Java class in your project, as shown in the following example:

   Sample implementation of the `KieServicesClientBuilder` interface

       public class MinaClientBuilderImpl implements KieServicesClientBuilder {  (1)

           public String getImplementedCapability() {  (2)
               return "BRM-Mina";
           }

           public Map<Class<?>, Object> build(KieServicesConfiguration configuration, ClassLoader classLoader) {  (3)
               Map<Class<?>, Object> services = new HashMap<Class<?>, Object>();

               services.put(RulesMinaServicesClient.class, new RulesMinaServicesClientImpl(configuration, classLoader));

               return services;
           }

       }

   1 | Enables you to provide additional client APIs to the generic KIE Server client infrastructure
   2 | Defines the KIE Server capability (extension) that the client uses
   3 | Provides a map of the client implementations, where the key is the interface and the value is the fully initialized implementation

5. To make the new client API discoverable for the KIE Server client, create a `META-INF/services/org.kie.server.client.helper.KieServicesClientBuilder` file in your Maven project and add the fully qualified class name of the `KieServicesClientBuilder` implementation class within the file. For this example, the file contains the single line `org.kie.server.ext.mina.client.MinaClientBuilderImpl`.

6. Build your project and copy the resulting JAR file into the `~/kie-server.war/WEB-INF/lib` directory of your project.

7. Start KIE Server and deploy the built project to the running KIE Server. You can deploy the project using either the Business Central interface or the KIE Server REST API (a `PUT` request to `http://SERVER:PORT/kie-server/services/rest/server/containers/{containerId}`).

   After your project is deployed on a running KIE Server, you can start interacting with your new KIE Server client. You use your new client in the same way as the standard KIE Server client, by creating the client configuration and client instance, retrieving the service client by type, and invoking client methods.

   For this example, you can create a `RulesMinaServiceClient` client instance and invoke operations on KIE Server through the MINA transport:

   Sample implementation to create the `RulesMinaServiceClient` client

       protected RulesMinaServicesClient buildClient() {
           KieServicesConfiguration configuration = KieServicesFactory.newRestConfiguration("localhost:9123", null, null);
           List<String> capabilities = new ArrayList<String>();
           // Explicitly add capabilities (the MINA client does not respond to `get-server-info` requests):
           capabilities.add("BRM-Mina");

           configuration.setCapabilities(capabilities);
           configuration.setMarshallingFormat(MarshallingFormat.JSON);

           configuration.addJaxbClasses(extraClasses);

           KieServicesClient kieServicesClient =  KieServicesFactory.newKieServicesClient(configuration);

           RulesMinaServicesClient rulesClient = kieServicesClient.getServicesClient(RulesMinaServicesClient.class);

           return rulesClient;
       }

   Sample configuration to invoke operations on KIE Server through the MINA transport

       RulesMinaServicesClient rulesClient = buildClient();

       List<Command<?>> commands = new ArrayList<Command<?>>();
       BatchExecutionCommand executionCommand = commandsFactory.newBatchExecution(commands, "defaultKieSession");

       Person person = new Person();
       person.setName("mary");
       commands.add(commandsFactory.newInsert(person, "person"));
       commands.add(commandsFactory.newFireAllRules("fired"));

       ServiceResponse<String> response = rulesClient.executeCommands(containerId, executionCommand);
       Assert.assertNotNull(response);

       Assert.assertEquals(ResponseType.SUCCESS, response.getType());

       String data = response.getResult();

       Marshaller marshaller = MarshallerFactory.getMarshaller(extraClasses, MarshallingFormat.JSON, this.getClass().getClassLoader());

       ExecutionResultImpl results = marshaller.unmarshall(data, ExecutionResultImpl.class);
       Assert.assertNotNull(results);

       Object personResult = results.getValue("person");
       Assert.assertTrue(personResult instanceof Person);

       Assert.assertEquals("mary", ((Person) personResult).getName());
       Assert.assertEquals("JBoss Community", ((Person) personResult).getAddress());
       Assert.assertEquals(true, ((Person) personResult).isRegistered());

### 7.5. Kie Server setup

| Server setup and registration changed significantly from versions 6.2 and before. The following applies only to version 6.3 and forward.

#### 7.5.1. Managed Kie Server

A managed instance is one that requires a KIE Server controller to be available to properly start up the Kie Server instance.

The KIE Server controller is a component responsible for keeping and managing a Kie Server Configuration in centralized way. Each KIE Server controller can manage multiple configurations at once and there can be multiple KIE Server controllers in the environment. Managed KIE Servers can be configured with a list of KIE Server controllers but will connect to only one at a time.

| It’s important to mention that even though there can be multiple KIE Server controllers they should be kept in sync to make sure that regardless which one of them is contacted by KIE Server instance it will provide same set of configuration.

At startup, if a Kie Server is configured with a list of KIE Server controllers, it will try successively to connect to each of them until a connection is successfully established with one of them. If for any reason a connection can’t be established, the server will not start, even if there is local storage available with configuration. This happens by design in order to ensure consistency. For instance, if the Kie Server was down and the configuration has changed, this restriction guarantees that it will run with up to date configuration or not at all.

| In order to run the Kie Server in standalone mode, without connecting to any KIE Server controllers, please see "Unmanaged Kie Server".

The configuration sets, among other things:

- kie containers to be deployed and started

- configuration items - currently this is a placeholder for further enhancements that will allow remotely configure KIE Execution Server components - timers, persistence, etc

The KIE Server controller, besides providing configuration management, is also responsible for overall management of Kie Servers. It provides a REST api that is divided into two parts:

- the KIE Server controller itself that is exposed to interact with KIE Execution Server instances

- an administration API that allows to remotely manage Kie Server instances:

  - add/remove servers

  - add/remove containers to/from the servers

  - start/stop containers on servers

The KIE Server controller deals only with the Kie Server configuration or definition to put it differently. It does not handle any runtime components of KIE Execution Server instances. They are always considered remote to KIE Server controller. The KIE Server controller is responsible for persisting the configuration to preserve restarts of the KIE Server controller itself. It should manage the synchronization as well in case multiple KIE Server controllers are configured to keep all definitions up to date on all instances of the KIE Server controller.

By default KIE Server controller is shipped with Business Central and provides a fully featured management interface (both REST api and UI). It uses underlying git repository as persistent store and thus when GIT repositories are clustered (using Apache Zookeeper and Apache Helix) it will cover the KIE Server controllers synchronization as well.

The diagram above illustrates the single KIE Server controller (Business Central) setup with multiple Kie Server instances managed by it.

The diagram below illustrates the clustered setup where there are multiple instances of KIE Server controller synchronized over Zookeeper.

In the above diagram we can see that the Kie Server instances are capable of connecting to any KIE Server controllers, but they will connect to only one. Each instance will attempt to connect to KIE Server controller as long as it can reach one. Once connection is established with one of the KIE Server controllers it will skip the others.

##### 7.5.1.1. Working with managed servers

There are two approaches that users can take when working with managed KIE Server instances:

- Configuration first: with this approach, a user will start working with the KIE Server controller (either UI or REST api) and create and configure Kie Server definitions. That consists basically of an identification for the server definition (id and name + optionally version for improved readability) and the configuration for the Kie Containers to run on the server.

- Registration first: with this approach, the Kie Server instances are started first and auto register themselves on KIE Server controller. The user then can configure the Kie Containers. This option simply skips the registration step done in the first approach and populates it with server id, name and version directly upon auto registration. There are no other differences between the two approaches.

#### 7.5.2. Unmanaged KIE Execution Server

An unmanaged Kie Server is in turn just a standalone instance, and thus must be configured individually using REST/JMS api from the Kie Server itself. There is no KIE Server controller involved. The configuration is automatically persisted by the server into a file and that is used as the internal server state, in case of restarts.

The configuration is updated during the following operations:

- deploy Kie Container

- undeploy Kie Container

- start Kie Container

- stop Kie Container

| If the Kie Server is restarted, it will try to establish the same state that was persisted before shutdown. That means that Kie Containers that were running, will be started, but the ones that were stopped/disposed before, will not.

In most use cases, the Kie Server should be executed in managed mode as that provides some benefits, like a web user interface (if using Business Central as a KIE Server controller) and some facilities for clustering.

### 7.6. Creating a Kie Container

Once your Execution Server is registered, you can start adding Kie Containers to it.

Kie Containers are self contained environments that have been provisioned to hold instances of your packaged and deployed rule instances.

1. Start by clicking the \+ icon next to the Execution Server where you want to deploy your Container. This will bring up the New Container screen.

2. If you know the Group Name, Artifact Id and Version (GAV) of your deployed package, then you can enter those details and click the Ok button to select that instance (and provide a name for the Container);

3. If you don’t know these values, you can search Business Central for all packages that can be deployed. Click the Search button without entering any value in the search field (you can narrow your search by entering any term that you know exists in the package that you want to deploy).

   | INSERT SCREENSHOT HERE

   The figure above shows that there are three deployable packages available to be used as containers on the Execution Server. Select the one that you want by clicking the Select button. This will auto-populate the GAV and you can then click the Ok button to use this deployable as the new Container.

4. Optionally, enter an alias for this Container, which you can use instead of the container name while accessing the execution server. By default, the alias is the related Artifact Id.

   | You can configure the same alias for different containers. When you use the alias, the latest version of associated containers is executed. This can be helpful when you deploy a new container version but do not want to change the client codes.

5. Enter a name for this Container at the top and then press the Ok button.

   | The Container name must be unique inside each execution server and must not contain any spaces.

| Just below the GAV row, you will see an uneditable row that shows you the URL for your Container against which you will be able to execute REST commands.

### 7.7. Managing Containers

Containers within the Execution Server can be started, stopped and updated from within Business Central.⁠

#### 7.7.1. Starting a Container

Once registered, a Container is in the 'Stopped' mode. It can be started by first selecting it and then clicking the Start button. You can also select multiple Containers and start them all at the same time.

Once the Container is in the 'Running' mode, a green arrow appears next to it. If there are any errors starting the Container(s), red icons appear next to Containers and the Execution Server that they are deployed on.

You should check the logs of both the Execution Server and the current Business Central to see what the errors are before redeploying the Containers (and possibly the Execution Server).⁠

#### 7.7.2. Stopping and Deleting a Container

Similar to starting a Container, select the Container(s) that you want to stop (or delete) and click the Stop button (which replaces the Start button for that Container once it has entered the 'Running' mode) or the Delete button.⁠

#### 7.7.3. Updating a Container

You can update deployed `KieContainers` without restarting the Execution Server. This is useful in cases where the Business Rules change, creating new versions of packages to be provisioned.

You can have multiple versions of the same package provisioned and deployed, each to a different `KieContainer`.

To update deployments in a `KieContainer` dynamically, click the icon next to the Container. This will open up the Container Info screen. An example of this screen is shown here:

| INSERT SCREENSHOT HERE

The Container Info screen is a useful tool because it not only allows you to see the endpoint for this `KieContainer`, but it also allows you to either manually or automatically refresh the provision if an update is available. The update can be manual or automatic:

Manual Update: To manually update a `KieContainer`, enter the new Version number in the Version box and click the Update button. You can of course, update the Group Id or the Artifact Id , if these have changed as well. Once updated, the Execution server updates the container and shows you the resolved GAV attributes at the bottom of the screen in the Resolved Release Id section.

Automatic Update: If you want a deployed Container to always have the latest version of your deployment without manually editing it, you will need to set the Version property to the value of `LATEST` and start a `Scanner`. This will ensure that the deployed provision always contains the latest version. The Scanner can be started just once on demand by clicking the Scan Now button or you can start it in the background with scans happening at a specified interval (in milliseconds).You can also set this value to `LATEST` when you are first creating this deployment. The Resolved Release Id in this case will show you the actual, latest version number.

### 7.8. KIE Server REST API for KIE containers and business assets

OptaPlanner provides a KIE Server REST API that you can use to interact with your KIE containers and business assets (such as business rules, processes, and solvers) in OptaPlanner without using the Business Central user interface. This API support enables you to maintain your OptaPlanner resources more efficiently and optimize your integration and development with OptaPlanner.

With the KIE Server REST API, you can perform the following actions:

- Deploy or dispose KIE containers

- Retrieve and update KIE container information

- Return KIE Server status and basic information

- Retrieve and update business asset information

- Execute business assets (such as rules and processes)

KIE Server REST API requests require the following components:

Authentication

  The KIE Server REST API requires HTTP Basic authentication or token-based authentication for the user role `kie-server`. To view configured user roles for your OptaPlanner distribution, navigate to `~/$SERVER_HOME/standalone/configuration/application-roles.properties` and `~/application-users.properties`.

  To add a user with the `kie-server` role, navigate to `~/$SERVER_HOME/bin` and run the following command:

      $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['kie-server'])"

  For more information about user roles and OptaPlanner installation options, see

HTTP headers

  The KIE Server REST API requires the following HTTP headers for API requests:

  - `Accept`: Data format accepted by your requesting client:

    - `application/json` (JSON)

    - `application/xml` (XML, for JAXB or XSTREAM)

  - `Content-Type`: Data format of your `POST` or `PUT` API request data:

    - `application/json` (JSON)

    - `application/xml` (XML, for JAXB or XSTREAM)

  - `X-KIE-ContentType`: Required header for `application/xml` XSTREAM API requests and responses:

    - `XSTREAM`

HTTP methods

  The KIE Server REST API supports the following HTTP methods for API requests:

  - `GET`: Retrieves specified information from a specified resource endpoint

  - `POST`: Updates a resource or resource instance

  - `PUT`: Updates or creates a resource or resource instance

  - `DELETE`: Deletes a resource or resource instance

Base URL

  The base URL for KIE Server REST API requests is `http://SERVER:PORT/kie-server/services/rest/`, such as `http://localhost:8080/kie-server/services/rest/`.

Endpoints

  KIE Server REST API endpoints, such as `/server/containers/{containerId}` for a specified KIE container, are the URIs that you append to the KIE Server REST API base URL to access the corresponding resource or type of resource in OptaPlanner.

  Example request URL for `/server/containers/{containerId}` endpoint

  `http://localhost:8080/kie-server/services/rest/server/containers/MyContainer`

Request parameters and request data

  Many KIE Server REST API requests require specific parameters in the request URL path to identify or filter specific resources and to perform specific actions. You can append URL parameters to the endpoint in the format `?<PARAM>=<VALUE>&<PARAM>=<VALUE>`.

  Example GET request URL with parameters

  `http://localhost:8080/kie-server/services/rest/server/containers?groupId=com.redhat&artifactId=Project1&version=1.0&status=STARTED`

  HTTP `POST` and `PUT` requests may additionally require a request body or file with data to accompany the request.

  Example POST request URL and JSON request body data

  `http://localhost:8080/kie-server/services/rest/server/containers/MyContainer/release-id`

      {
        "release-id": {
          "artifact-id": "Project1",
          "group-id": "com.redhat",
          "version": "1.1"
        }
      }

#### 7.8.1. Sending requests with the KIE Server REST API using a REST client or curl utility

The KIE Server REST API enables you to interact with your KIE containers and business assets (such as business rules, processes, and solvers) in OptaPlanner without using the Business Central user interface. You can send KIE Server REST API requests using any REST client or curl utility.

Prerequisites

- KIE Server is installed and running.

- You have `kie-server` user role access to KIE Server.

Procedure

1. Identify the relevant API endpoint to which you want to send a request, such as `[GET] /server/containers` to retrieve KIE containers from KIE Server.

2. In a REST client or curl utility, enter the following components for a `GET` request to `/server/containers`. Adjust any request details according to your use case.

   For REST client:

   - Authentication: Enter the user name and password of the KIE Server user with the `kie-server` role.

   - HTTP Headers: Set the following header:

     - `Accept`: `application/json`

   - HTTP method: Set to `GET`.

   - URL: Enter the KIE Server REST API base URL and endpoint, such as `http://localhost:8080/kie-server/services/rest/server/containers`.

   For curl utility:

   - `-u`: Enter the user name and password of the KIE Server user with the `kie-server` role.

   - `-H`: Set the following header:

     - `Accept`: `application/json`

   - `-X`: Set to `GET`.

   - URL: Enter the KIE Server REST API base URL and endpoint, such as `http://localhost:8080/kie-server/services/rest/server/containers`.

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -X GET "http://localhost:8080/kie-server/services/rest/server/containers"

3. Execute the request and review the KIE Server response.

   Example server response (JSON):

       {
         "type": "SUCCESS",
         "msg": "List of created containers",
         "result": {
           "kie-containers": {
             "kie-container": [
               {
                 "container-id": "itorders_1.0.0-SNAPSHOT",
                 "release-id": {
                   "group-id": "itorders",
                   "artifact-id": "itorders",
                   "version": "1.0.0-SNAPSHOT"
                 },
                 "resolved-release-id": {
                   "group-id": "itorders",
                   "artifact-id": "itorders",
                   "version": "1.0.0-SNAPSHOT"
                 },
                 "status": "STARTED",
                 "scanner": {
                   "status": "DISPOSED",
                   "poll-interval": null
                 },
                 "config-items": [],
                 "container-alias": "itorders"
               }
             ]
           }
         }
       }

4. For this example, copy or note the project `group-id`, `artifact-id`, and `version` (GAV) data from one of the deployed KIE containers returned in the response.

5. In your REST client or curl utility, send another API request with the following components for a `PUT` request to `/server/containers/{containerId}` to deploy a new KIE container with the copied project GAV data. Adjust any request details according to your use case.

   For REST client:

   - Authentication: Enter the user name and password of the KIE Server user with the `kie-server` role.

   - HTTP Headers: Set the following headers:

     - `Accept`: `application/json`

     - `Content-Type`: `application/json`

       | When you add `fields=not_null` to `Content-Type`, the null fields are excluded from the REST API response.

   - HTTP method: Set to `PUT`.

   - URL: Enter the KIE Server REST API base URL and endpoint, such as `http://localhost:8080/kie-server/services/rest/server/containers/MyContainer`.

   - Request body: Add a JSON request body with the configuration items for the new KIE container:

       {
         "config-items": [
           {
             "itemName": "RuntimeStrategy",
             "itemValue": "SINGLETON",
             "itemType": "java.lang.String"
           },
           {
             "itemName": "MergeMode",
             "itemValue": "MERGE_COLLECTIONS",
             "itemType": "java.lang.String"
           },
           {
             "itemName": "KBase",
             "itemValue": "",
             "itemType": "java.lang.String"
           },
           {
             "itemName": "KSession",
             "itemValue": "",
             "itemType": "java.lang.String"
           }
         ],
         "release-id": {
           "group-id": "itorders",
           "artifact-id": "itorders",
           "version": "1.0.0-SNAPSHOT"
         },
         "scanner": {
           "poll-interval": "5000",
           "status": "STARTED"
         }
       }

   For curl utility:

   - `-u`: Enter the user name and password of the KIE Server user with the `kie-server` role.

   - `-H`: Set the following headers:

     - `Accept`: `application/json`

     - `Content-Type`: `application/json`

       | When you add `fields=not_null` to `Content-Type`, the null fields are excluded from the REST API response.

   - `-X`: Set to `PUT`.

   - URL: Enter the KIE Server REST API base URL and endpoint, such as `http://localhost:8080/kie-server/services/rest/server/containers/MyContainer`.

   - `-d`: Add a JSON request body or file (`@file.json`) with the configuration items for the new KIE container:

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -H "Content-Type: application/json" -X PUT "http://localhost:8080/kie-server/services/rest/server/containers/MyContainer" -d "{ \"config-items\": [ { \"itemName\": \"RuntimeStrategy\", \"itemValue\": \"SINGLETON\", \"itemType\": \"java.lang.String\" }, { \"itemName\": \"MergeMode\", \"itemValue\": \"MERGE_COLLECTIONS\", \"itemType\": \"java.lang.String\" }, { \"itemName\": \"KBase\", \"itemValue\": \"\", \"itemType\": \"java.lang.String\" }, { \"itemName\": \"KSession\", \"itemValue\": \"\", \"itemType\": \"java.lang.String\" } ], \"release-id\": { \"group-id\": \"itorders\", \"artifact-id\": \"itorders\", \"version\": \"1.0.0-SNAPSHOT\" }, \"scanner\": { \"poll-interval\": \"5000\", \"status\": \"STARTED\" }}"

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -H "Content-Type: application/json" -X PUT "http://localhost:8080/kie-server/services/rest/server/containers/MyContainer" -d @my-container-configs.json

6. Execute the request and review the KIE Server response.

   Example server response (JSON):

       {
         "type": "SUCCESS",
         "msg": "Container MyContainer successfully deployed with module itorders:itorders:1.0.0-SNAPSHOT.",
         "result": {
           "kie-container": {
             "container-id": "MyContainer",
             "release-id": {
               "group-id": "itorders",
               "artifact-id": "itorders",
               "version": "1.0.0-SNAPSHOT"
             },
             "resolved-release-id": {
               "group-id": "itorders",
               "artifact-id": "itorders",
               "version": "1.0.0-SNAPSHOT"
             },
             "status": "STARTED",
             "scanner": {
               "status": "STARTED",
               "poll-interval": 5000
             },
             "config-items": [],
             "messages": [
               {
                 "severity": "INFO",
                 "timestamp": {
                   "java.util.Date": 1540584717937
                 },
                 "content": [
                   "Container MyContainer successfully created with module itorders:itorders:1.0.0-SNAPSHOT."
                 ]
               }
             ],
             "container-alias": null
           }
         }
       }

   If you encounter request errors, review the returned error code messages and adjust your request accordingly.

#### 7.8.2. Sending requests with the KIE Server REST API using the Swagger interface

The KIE Server REST API supports a Swagger web interface that you can use instead of a standalone REST client or curl utility to interact with your KIE containers and business assets (such as business rules, processes, and solvers) in OptaPlanner without using the Business Central user interface.

| By default, the Swagger web interface for KIE Server is enabled by the `org.kie.swagger.server.ext.disabled=false` system property. To disable the Swagger web interface in KIE Server, set this system property to `true`.

Prerequisites

- KIE Server is installed and running.

- You have `kie-server` user role access to KIE Server.

Procedure

1. In a web browser, navigate to `http://SERVER:PORT/kie-server/docs`, such as `http://localhost:8080/kie-server/docs`, and log in with the user name and password of the KIE Server user with the `kie-server` role.

2. In the Swagger page, select the relevant API endpoint to which you want to send a request, such as KIE Server and KIE containers → [GET] /server/containers to retrieve KIE containers from KIE Server.

3. Click Try it out and provide any optional parameters by which you want to filter results, if needed.

4. In the Response content type drop-down menu, select the desired format of the server response, such as application/json for JSON format.

5. Click Execute and review the KIE Server response.

   Example server response (JSON):

       {
         "type": "SUCCESS",
         "msg": "List of created containers",
         "result": {
           "kie-containers": {
             "kie-container": [
               {
                 "container-id": "itorders_1.0.0-SNAPSHOT",
                 "release-id": {
                   "group-id": "itorders",
                   "artifact-id": "itorders",
                   "version": "1.0.0-SNAPSHOT"
                 },
                 "resolved-release-id": {
                   "group-id": "itorders",
                   "artifact-id": "itorders",
                   "version": "1.0.0-SNAPSHOT"
                 },
                 "status": "STARTED",
                 "scanner": {
                   "status": "DISPOSED",
                   "poll-interval": null
                 },
                 "config-items": [],
                 "container-alias": "itorders"
               }
             ]
           }
         }
       }

6. For this example, copy or note the project `group-id`, `artifact-id`, and `version` (GAV) data from one of the deployed KIE containers returned in the response.

7. In the Swagger page, navigate to the KIE Server and KIE containers → [PUT] /server/containers/{containerId} endpoint to send another request to deploy a new KIE container with the copied project GAV data. Adjust any request details according to your use case.

8. Click Try it out and enter the following components for the request:

   - containerId: Enter the ID of the new KIE container, such as `MyContainer`.

   - body: Set the Parameter content type to the desired request body format, such as application/json for JSON format, and add a request body with the configuration items for the new KIE container:

       {
         "config-items": [
           {
             "itemName": "RuntimeStrategy",
             "itemValue": "SINGLETON",
             "itemType": "java.lang.String"
           },
           {
             "itemName": "MergeMode",
             "itemValue": "MERGE_COLLECTIONS",
             "itemType": "java.lang.String"
           },
           {
             "itemName": "KBase",
             "itemValue": "",
             "itemType": "java.lang.String"
           },
           {
             "itemName": "KSession",
             "itemValue": "",
             "itemType": "java.lang.String"
           }
         ],
         "release-id": {
           "group-id": "itorders",
           "artifact-id": "itorders",
           "version": "1.0.0-SNAPSHOT"
         },
         "scanner": {
           "poll-interval": "5000",
           "status": "STARTED"
         }
       }

9. In the Response content type drop-down menu, select the desired format of the server response, such as application/json for JSON format.

10. Click Execute and review the KIE Server response.

    Example server response (JSON):

        {
          "type": "SUCCESS",
          "msg": "Container MyContainer successfully deployed with module itorders:itorders:1.0.0-SNAPSHOT.",
          "result": {
            "kie-container": {
              "container-id": "MyContainer",
              "release-id": {
                "group-id": "itorders",
                "artifact-id": "itorders",
                "version": "1.0.0-SNAPSHOT"
              },
              "resolved-release-id": {
                "group-id": "itorders",
                "artifact-id": "itorders",
                "version": "1.0.0-SNAPSHOT"
              },
              "status": "STARTED",
              "scanner": {
                "status": "STARTED",
                "poll-interval": 5000
              },
              "config-items": [],
              "messages": [
                {
                  "severity": "INFO",
                  "timestamp": {
                    "java.util.Date": 1540584717937
                  },
                  "content": [
                    "Container MyContainer successfully created with module itorders:itorders:1.0.0-SNAPSHOT."
                  ]
                }
              ],
              "container-alias": null
            }
          }
        }

    If you encounter request errors, review the returned error code messages and adjust your request accordingly.

#### 7.8.3. Supported KIE Server REST API endpoints

The KIE Server REST API provides endpoints for the following types of resources in OptaPlanner:

- KIE Server and KIE containers

- KIE session assets (for runtime commands)

- DMN assets

- Planning solvers

The KIE Server REST API base URL is `http://SERVER:PORT/kie-server/services/rest/`. All requests require HTTP Basic authentication or token-based authentication for the `kie-server` user role.

For the full list of KIE Server REST API endpoints and descriptions, use one of the following resources:

- Execution Server REST API on the jBPM Documentation page (static)

- Swagger UI for the KIE Server REST API at `http://SERVER:PORT/kie-server/docs` (dynamic, requires running KIE Server)

  | By default, the Swagger web interface for KIE Server is enabled by the `org.kie.swagger.server.ext.disabled=false` system property. To disable the Swagger web interface in KIE Server, set this system property to `true`.

### 7.9. KIE Server Java client API for KIE containers and business assets

OptaPlanner provides a KIE Server Java client API that enables you to connect to KIE Server using REST protocol from your Java client application. You can use the KIE Server Java client API as an alternative to the KIE Server REST API to interact with your KIE containers and business assets (such as business rules, processes, and solvers) in OptaPlanner without using the Business Central user interface. This API support enables you to maintain your OptaPlanner resources more efficiently and optimize your integration and development with OptaPlanner.

With the KIE Server Java client API, you can perform the following actions also supported by the KIE Server REST API:

- Deploy or dispose KIE containers

- Retrieve and update KIE container information

- Return KIE Server status and basic information

- Retrieve and update business asset information

- Execute business assets (such as rules and processes)

KIE Server Java client API requests require the following components:

Authentication

  The KIE Server Java client API requires HTTP Basic authentication for the user role `kie-server`. To view configured user roles for your OptaPlanner distribution, navigate to `~/$SERVER_HOME/standalone/configuration/application-roles.properties` and `~/application-users.properties`.

  To add a user with the `kie-server` role, navigate to `~/$SERVER_HOME/bin` and run the following command:

      $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['kie-server'])"

  For more information about user roles and OptaPlanner installation options, see

Project dependencies

  The KIE Server Java client API requires the following dependencies on the relevant classpath of your Java project:

      <!-- For remote execution on KIE Server -->
      <dependency>
        <groupId>org.kie.server</groupId>
        <artifactId>kie-server-client</artifactId>
        <version>${optaplanner.version}</version>
      </dependency>

      <!-- For runtime commands -->
      <dependency>
        <groupId>org.drools</groupId>
        <artifactId>drools-compiler</artifactId>
        <scope>runtime</scope>
        <version>${optaplanner.version}</version>
      </dependency>

      <!-- For debug logging (optional) -->
      <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
      </dependency>

  The `<version>` for OptaPlanner dependencies is the Maven artifact version for OptaPlanner currently used in your project (for example, 7.59.0.Final).

Client request configuration

  All Java client requests with the KIE Server Java client API must define at least the following server communication components:

  - Credentials of the `kie-server` user

  - KIE Server location, such as `http://localhost:8080/kie-server/services/rest/server`

  - Marshalling format for API requests and responses (JSON, JAXB, or XSTREAM)

  - A `KieServicesConfiguration` object and a `KieServicesClient` object, which serve as the entry point for starting the server communication using the Java client API

  - A `KieServicesFactory` object defining REST protocol and user access

  - Any other client services used, such as `RuleServicesClient`, `ProcessServicesClient`, or `QueryServicesClient`

  The following are examples of basic and advanced client configurations with these components:

  Basic client configuration example

      import org.kie.server.api.marshalling.MarshallingFormat;
      import org.kie.server.client.KieServicesClient;
      import org.kie.server.client.KieServicesConfiguration;
      import org.kie.server.client.KieServicesFactory;

      public class MyConfigurationObject {

        private static final String URL = "http://localhost:8080/kie-server/services/rest/server";
        private static final String USER = "baAdmin";
        private static final String PASSWORD = "password@1";

        private static final MarshallingFormat FORMAT = MarshallingFormat.JSON;

        private static KieServicesConfiguration conf;
        private static KieServicesClient kieServicesClient;

        public static void initialize() {
          conf = KieServicesFactory.newRestConfiguration(URL, USER, PASSWORD);

          //If you use custom classes, such as Obj.class, add them to the configuration.
          Set<Class<?>> extraClassList = new HashSet<Class<?>>();
          extraClassList.add(Obj.class);
          conf.addExtraClasses(extraClassList);

          conf.setMarshallingFormat(FORMAT);
          kieServicesClient = KieServicesFactory.newKieServicesClient(conf);
        }
      }

  Advanced client configuration example with additional client services

      import org.kie.server.api.marshalling.MarshallingFormat;
      import org.kie.server.client.CaseServicesClient;
      import org.kie.server.client.DMNServicesClient;
      import org.kie.server.client.DocumentServicesClient;
      import org.kie.server.client.JobServicesClient;
      import org.kie.server.client.KieServicesClient;
      import org.kie.server.client.KieServicesConfiguration;
      import org.kie.server.client.KieServicesFactory;
      import org.kie.server.client.ProcessServicesClient;
      import org.kie.server.client.QueryServicesClient;
      import org.kie.server.client.RuleServicesClient;
      import org.kie.server.client.SolverServicesClient;
      import org.kie.server.client.UIServicesClient;
      import org.kie.server.client.UserTaskServicesClient;
      import org.kie.server.api.model.instance.ProcessInstance;
      import org.kie.server.api.model.KieContainerResource;
      import org.kie.server.api.model.ReleaseId;

      public class MyAdvancedConfigurationObject {

          // REST API base URL, credentials, and marshalling format
          private static final String URL = "http://localhost:8080/kie-server/services/rest/server";
          private static final String USER = "baAdmin";
          private static final String PASSWORD = "password@1";;

          private static final MarshallingFormat FORMAT = MarshallingFormat.JSON;

          private static KieServicesConfiguration conf;

          // KIE client for common operations
          private static KieServicesClient kieServicesClient;

          // Rules client
          private static RuleServicesClient ruleClient;

          // Process automation clients
          private static CaseServicesClient caseClient;
          private static DocumentServicesClient documentClient;
          private static JobServicesClient jobClient;
          private static ProcessServicesClient processClient;
          private static QueryServicesClient queryClient;
          private static UIServicesClient uiClient;
          private static UserTaskServicesClient userTaskClient;

          // DMN client
          private static DMNServicesClient dmnClient;

          // Planning client
          private static SolverServicesClient solverClient;

          public static void main(String[] args) {
              initializeKieServerClient();
              initializeDroolsServiceClients();
              initializeJbpmServiceClients();
              initializeSolverServiceClients();
          }

          public static void initializeKieServerClient() {
              conf = KieServicesFactory.newRestConfiguration(URL, USER, PASSWORD);
              conf.setMarshallingFormat(FORMAT);
              kieServicesClient = KieServicesFactory.newKieServicesClient(conf);
          }

          public static void initializeDroolsServiceClients() {
              ruleClient = kieServicesClient.getServicesClient(RuleServicesClient.class);
              dmnClient = kieServicesClient.getServicesClient(DMNServicesClient.class);
          }

          public static void initializeJbpmServiceClients() {
              caseClient = kieServicesClient.getServicesClient(CaseServicesClient.class);
              documentClient = kieServicesClient.getServicesClient(DocumentServicesClient.class);
              jobClient = kieServicesClient.getServicesClient(JobServicesClient.class);
              processClient = kieServicesClient.getServicesClient(ProcessServicesClient.class);
              queryClient = kieServicesClient.getServicesClient(QueryServicesClient.class);
              uiClient = kieServicesClient.getServicesClient(UIServicesClient.class);
              userTaskClient = kieServicesClient.getServicesClient(UserTaskServicesClient.class);
          }

          public static void initializeSolverServiceClients() {
              solverClient = kieServicesClient.getServicesClient(SolverServicesClient.class);
          }
      }

#### 7.9.1. Sending requests with the KIE Server Java client API

The KIE Server Java client API enables you to connect to KIE Server using REST protocol from your Java client application. You can use the KIE Server Java client API as an alternative to the KIE Server REST API to interact with your KIE containers and business assets (such as business rules, processes, and solvers) in OptaPlanner without using the Business Central user interface.

Prerequisites

- KIE Server is installed and running.

- You have `kie-server` user role access to KIE Server.

- You have a Java project with OptaPlanner resources.

Procedure

1. In your client application, ensure that the following dependencies have been added to the relevant classpath of your Java project:

       <!-- For remote execution on KIE Server -->
       <dependency>
         <groupId>org.kie.server</groupId>
         <artifactId>kie-server-client</artifactId>
         <version>${optaplanner.version}</version>
       </dependency>

       <!-- For runtime commands -->
       <dependency>
         <groupId>org.drools</groupId>
         <artifactId>drools-compiler</artifactId>
         <scope>runtime</scope>
         <version>${optaplanner.version}</version>
       </dependency>

       <!-- For debug logging (optional) -->
       <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-classic</artifactId>
         <version>${logback.version}</version>
       </dependency>

2. In the `~/kie/server/client` folder of the Java client API in GitHub , identify the relevant Java client for the request you want to send, such as `KieServicesClient` to access client services for KIE containers and other assets in KIE Server.

3. In your client application, create a `.java` class for the API request. The class must contain the necessary imports, KIE Server location and user credentials, a `KieServicesClient` object, and the client method to execute, such as `createContainer` and `disposeContainer` from the `KieServicesClient` client. Adjust any configuration details according to your use case.

   Creating and disposing a container

       import org.kie.server.api.marshalling.MarshallingFormat;
       import org.kie.server.client.KieServicesClient;
       import org.kie.server.client.KieServicesConfiguration;
       import org.kie.server.client.KieServicesFactory;
       import org.kie.server.api.model.KieContainerResource;
       import org.kie.server.api.model.ServiceResponse;

       public class MyConfigurationObject {

         private static final String URL = "http://localhost:8080/kie-server/services/rest/server";
         private static final String USER = "baAdmin";
         private static final String PASSWORD = "password@1";

         private static final MarshallingFormat FORMAT = MarshallingFormat.JSON;

         private static KieServicesConfiguration conf;
         private static KieServicesClient kieServicesClient;

         public static void initialize() {
           conf = KieServicesFactory.newRestConfiguration(URL, USER, PASSWORD);

         public void disposeAndCreateContainer() {
             System.out.println("== Disposing and creating containers ==");

             // Retrieve list of KIE containers
             List<KieContainerResource> kieContainers = kieServicesClient.listContainers().getResult().getContainers();
             if (kieContainers.size() == 0) {
                 System.out.println("No containers available...");
                 return;
             }

             // Dispose KIE container
             KieContainerResource container = kieContainers.get(0);
             String containerId = container.getContainerId();
             ServiceResponse<Void> responseDispose = kieServicesClient.disposeContainer(containerId);
             if (responseDispose.getType() == ResponseType.FAILURE) {
                 System.out.println("Error disposing " + containerId + ". Message: ");
                 System.out.println(responseDispose.getMsg());
                 return;
             }
             System.out.println("Success Disposing container " + containerId);
             System.out.println("Trying to recreate the container...");

             // Re-create KIE container
             ServiceResponse<KieContainerResource> createResponse = kieServicesClient.createContainer(containerId, container);
             if(createResponse.getType() == ResponseType.FAILURE) {
                 System.out.println("Error creating " + containerId + ". Message: ");
                 System.out.println(responseDispose.getMsg());
                 return;
             }
             System.out.println("Container recreated with success!");
             }
         }
       }

   You define service responses using the `org.kie.server.api.model.ServiceResponse<T>` object, where `T` represents the type of returned response. The `ServiceResponse` object has the following attributes:

   - `String message`: Returns the response message

   - `ResponseType type`: Returns either `SUCCESS` or `FAILURE`

   - `T result`: Returns the requested object

   In this example, when you dispose a container, the `ServiceResponse` returns a `Void` response. When you create a container, the `ServiceResponse` returns a `KieContainerResource` object.

   | A conversation between a client and a specific KIE Server container in a clustered environment is secured by a unique `conversationID`. The `conversationID` is transferred using the `X-KIE-ConversationId` REST header. If you update the container, unset the previous `conversationID`. Use `KieServiesClient.completeConversation()` to unset the `conversationID` for Java API.

4. Run the configured `.java` class from your project directory to execute the request, and review the KIE Server response.

   If you enabled debug logging, KIE Server responds with a detailed response according to your configured marshalling format, such as JSON.

   Example server response for a new KIE container (log):

       10:23:35.194 [main] INFO  o.k.s.a.m.MarshallerFactory - Marshaller extensions init
       10:23:35.396 [main] DEBUG o.k.s.client.balancer.LoadBalancer - Load balancer RoundRobinBalancerStrategy{availableEndpoints=[http://localhost:8080/kie-server/services/rest/server]} selected url 'http://localhost:8080/kie-server/services/rest/server'
       10:23:35.398 [main] DEBUG o.k.s.c.i.AbstractKieServicesClientImpl - About to send GET request to 'http://localhost:8080/kie-server/services/rest/server'
       10:23:35.440 [main] DEBUG o.k.s.c.i.AbstractKieServicesClientImpl - About to deserialize content:
        '{
         "type" : "SUCCESS",
         "msg" : "Kie Server info",
         "result" : {
           "kie-server-info" : {
             "id" : "default-kieserver",
             "version" : "7.11.0.Final-redhat-00003",
             "name" : "default-kieserver",
             "location" : "http://localhost:8080/kie-server/services/rest/server",
             "capabilities" : [ "KieServer", "BRM", "BPM", "CaseMgmt", "BPM-UI", "BRP", "DMN", "Swagger" ],
             "messages" : [ {
               "severity" : "INFO",
               "timestamp" : {
         "java.util.Date" : 1540814906533
       },
               "content" : [ "Server KieServerInfo{serverId='default-kieserver', version='7.11.0.Final-redhat-00003', name='default-kieserver', location='http://localhost:8080/kie-server/services/rest/server', capabilities=[KieServer, BRM, BPM, CaseMgmt, BPM-UI, BRP, DMN, Swagger], messages=null}started successfully at Mon Oct 29 08:08:26 EDT 2018" ]
             } ]
           }
         }
       }'
        into type: 'class org.kie.server.api.model.ServiceResponse'
       10:23:35.653 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - KieServicesClient connected to: default-kieserver version 7.11.0.Final-redhat-00003
       10:23:35.653 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Supported capabilities by the server: [KieServer, BRM, BPM, CaseMgmt, BPM-UI, BRP, DMN, Swagger]
       10:23:35.653 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Building services client for server capability KieServer
       10:23:35.653 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - No builder found for 'KieServer' capability
       10:23:35.654 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Building services client for server capability BRM
       10:23:35.654 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Builder 'org.kie.server.client.helper.DroolsServicesClientBuilder@6b927fb' for capability 'BRM'
       10:23:35.655 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Capability implemented by {interface org.kie.server.client.RuleServicesClient=org.kie.server.client.impl.RuleServicesClientImpl@4a94ee4}
       10:23:35.655 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Building services client for server capability BPM
       10:23:35.656 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Builder 'org.kie.server.client.helper.JBPMServicesClientBuilder@4cc451f2' for capability 'BPM'
       10:23:35.672 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Capability implemented by {interface org.kie.server.client.JobServicesClient=org.kie.server.client.impl.JobServicesClientImpl@1189dd52, interface org.kie.server.client.admin.ProcessAdminServicesClient=org.kie.server.client.admin.impl.ProcessAdminServicesClientImpl@36bc55de, interface org.kie.server.client.DocumentServicesClient=org.kie.server.client.impl.DocumentServicesClientImpl@564fabc8, interface org.kie.server.client.admin.UserTaskAdminServicesClient=org.kie.server.client.admin.impl.UserTaskAdminServicesClientImpl@16d04d3d, interface org.kie.server.client.QueryServicesClient=org.kie.server.client.impl.QueryServicesClientImpl@49ec71f8, interface org.kie.server.client.ProcessServicesClient=org.kie.server.client.impl.ProcessServicesClientImpl@1d2adfbe, interface org.kie.server.client.UserTaskServicesClient=org.kie.server.client.impl.UserTaskServicesClientImpl@36902638}
       10:23:35.672 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Building services client for server capability CaseMgmt
       10:23:35.672 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Builder 'org.kie.server.client.helper.CaseServicesClientBuilder@223d2c72' for capability 'CaseMgmt'
       10:23:35.676 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Capability implemented by {interface org.kie.server.client.admin.CaseAdminServicesClient=org.kie.server.client.admin.impl.CaseAdminServicesClientImpl@2b662a77, interface org.kie.server.client.CaseServicesClient=org.kie.server.client.impl.CaseServicesClientImpl@7f0eb4b4}
       10:23:35.676 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Building services client for server capability BPM-UI
       10:23:35.676 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Builder 'org.kie.server.client.helper.JBPMUIServicesClientBuilder@5c33f1a9' for capability 'BPM-UI'
       10:23:35.677 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Capability implemented by {interface org.kie.server.client.UIServicesClient=org.kie.server.client.impl.UIServicesClientImpl@223191a6}
       10:23:35.678 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Building services client for server capability BRP
       10:23:35.678 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Builder 'org.kie.server.client.helper.OptaplannerServicesClientBuilder@49139829' for capability 'BRP'
       10:23:35.679 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Capability implemented by {interface org.kie.server.client.SolverServicesClient=org.kie.server.client.impl.SolverServicesClientImpl@77fbd92c}
       10:23:35.679 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Building services client for server capability DMN
       10:23:35.679 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Builder 'org.kie.server.client.helper.DMNServicesClientBuilder@67c27493' for capability 'DMN'
       10:23:35.680 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Capability implemented by {interface org.kie.server.client.DMNServicesClient=org.kie.server.client.impl.DMNServicesClientImpl@35e2d654}
       10:23:35.680 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - Building services client for server capability Swagger
       10:23:35.680 [main] DEBUG o.k.s.c.impl.KieServicesClientImpl - No builder found for 'Swagger' capability
       10:23:35.681 [main] DEBUG o.k.s.client.balancer.LoadBalancer - Load balancer RoundRobinBalancerStrategy{availableEndpoints=[http://localhost:8080/kie-server/services/rest/server]} selected url 'http://localhost:8080/kie-server/services/rest/server'
       10:23:35.701 [main] DEBUG o.k.s.c.i.AbstractKieServicesClientImpl - About to send PUT request to 'http://localhost:8080/kie-server/services/rest/server/containers/employee-rostering3' with payload '{
         "container-id" : null,
         "release-id" : {
           "group-id" : "employeerostering",
           "artifact-id" : "employeerostering",
           "version" : "1.0.0-SNAPSHOT"
         },
         "resolved-release-id" : null,
         "status" : null,
         "scanner" : null,
         "config-items" : [ ],
         "messages" : [ ],
         "container-alias" : null
       }'
       10:23:38.071 [main] DEBUG o.k.s.c.i.AbstractKieServicesClientImpl - About to deserialize content:
        '{
         "type" : "SUCCESS",
         "msg" : "Container employee-rostering3 successfully deployed with module employeerostering:employeerostering:1.0.0-SNAPSHOT.",
         "result" : {
           "kie-container" : {
             "container-id" : "employee-rostering3",
             "release-id" : {
               "group-id" : "employeerostering",
               "artifact-id" : "employeerostering",
               "version" : "1.0.0-SNAPSHOT"
             },
             "resolved-release-id" : {
               "group-id" : "employeerostering",
               "artifact-id" : "employeerostering",
               "version" : "1.0.0-SNAPSHOT"
             },
             "status" : "STARTED",
             "scanner" : {
               "status" : "DISPOSED",
               "poll-interval" : null
             },
             "config-items" : [ ],
             "messages" : [ {
               "severity" : "INFO",
               "timestamp" : {
         "java.util.Date" : 1540909418069
       },
               "content" : [ "Container employee-rostering3 successfully created with module employeerostering:employeerostering:1.0.0-SNAPSHOT." ]
             } ],
             "container-alias" : null
           }
         }
       }'
        into type: 'class org.kie.server.api.model.ServiceResponse'

   If you encounter request errors, review the returned error code messages and adjust your Java configurations accordingly.

#### 7.9.2. Supported KIE Server Java clients

The following are some of the Java client services available in the `org.kie.server.client` package of your OptaPlanner distribution. You can use these services to interact with related resources in KIE Server similarly to the KIE Server REST API.

- `KieServicesClient`: Used as the entry point for other KIE Server Java clients, and used to interact with KIE containers

- `JobServicesClient`: Used to schedule, cancel, re-queue, and get job requests

- `RuleServicesClient`: Used to send commands to the server to perform rule-related operations, such as executing rules or inserting objects into the KIE session

- `SolverServicesClient`: Used to perform all Red Hat build of OptaPlanner operations, such as getting the solver state and the best solution, or disposing a solver

The `getServicesClient` method provides access to any of these clients:

    RuleServicesClient rulesClient = kieServicesClient.getServicesClient(RuleServicesClient.class);

For the full list of available KIE Server Java clients, see the Java client API source in GitHub.

#### 7.9.3. Example requests with the KIE Server Java client API

The following are examples of KIE Server Java client API requests for basic interactions with KIE Server. For the full list of available KIE Server Java clients, see the Java client API source in GitHub.

Listing KIE Server capabilities

  You can use the `org.kie.server.api.model.KieServerInfo` object to identify server capabilities. The `KieServicesClient` client requires the server capability information to correctly produce service clients. You can specify the capabilities globally in `KieServicesConfiguration`; otherwise they are automatically retrieved from KIE Server.

  Example request to return KIE Server capabilities

      public void listCapabilities() {

        KieServerInfo serverInfo = kieServicesClient.getServerInfo().getResult();
        System.out.print("Server capabilities:");

        for (String capability : serverInfo.getCapabilities()) {
          System.out.print(" " + capability);
        }

        System.out.println();
      }

Listing KIE containers in KIE Server

  KIE containers are represented by the `org.kie.server.api.model.KieContainerResource` object. The list of resources is represented by the `org.kie.server.api.model.KieContainerResourceList` object.

  Example request to return KIE containers from KIE Server

      public void listContainers() {
          KieContainerResourceList containersList = kieServicesClient.listContainers().getResult();
          List<KieContainerResource> kieContainers = containersList.getContainers();
          System.out.println("Available containers: ");
          for (KieContainerResource container : kieContainers) {
              System.out.println("\t" + container.getContainerId() + " (" + container.getReleaseId() + ")");
          }
      }

  You can optionally filter the KIE container results using an instance of the `org.kie.server.api.model.KieContainerResourceFilter` class, which is passed to the `org.kie.server.client.KieServicesClient.listContainers()` method.

  Example request to return KIE containers by release ID and status

      public void listContainersWithFilter() {

          // Filter containers by releaseId "org.example:container:1.0.0.Final" and status FAILED
          KieContainerResourceFilter filter = new KieContainerResourceFilter.Builder()
                  .releaseId("org.example", "container", "1.0.0.Final")
                  .status(KieContainerStatus.FAILED)
                  .build();

          // Using previously created KieServicesClient
          KieContainerResourceList containersList = kieServicesClient.listContainers(filter).getResult();
          List<KieContainerResource> kieContainers = containersList.getContainers();

          System.out.println("Available containers: ");

          for (KieContainerResource container : kieContainers) {
              System.out.println("\t" + container.getContainerId() + " (" + container.getReleaseId() + ")");
          }
      }

Creating and disposing KIE containers in KIE Server

  You can use the `createContainer` and `disposeContainer` methods in the `KieServicesClient` client to dispose and create KIE containers. In this example, when you dispose a container, the `ServiceResponse` returns a `Void` response. When you create a container, the `ServiceResponse` returns a `KieContainerResource` object.

  Example request to dispose and re-create a KIE container

      public void disposeAndCreateContainer() {
          System.out.println("== Disposing and creating containers ==");

          // Retrieve list of KIE containers
          List<KieContainerResource> kieContainers = kieServicesClient.listContainers().getResult().getContainers();
          if (kieContainers.size() == 0) {
              System.out.println("No containers available...");
              return;
          }

          // Dispose KIE container
          KieContainerResource container = kieContainers.get(0);
          String containerId = container.getContainerId();
          ServiceResponse<Void> responseDispose = kieServicesClient.disposeContainer(containerId);
          if (responseDispose.getType() == ResponseType.FAILURE) {
              System.out.println("Error disposing " + containerId + ". Message: ");
              System.out.println(responseDispose.getMsg());
              return;
          }
          System.out.println("Success Disposing container " + containerId);
          System.out.println("Trying to recreate the container...");

          // Re-create KIE container
          ServiceResponse<KieContainerResource> createResponse = kieServicesClient.createContainer(containerId, container);
          if(createResponse.getType() == ResponseType.FAILURE) {
              System.out.println("Error creating " + containerId + ". Message: ");
              System.out.println(responseDispose.getMsg());
              return;
          }
          System.out.println("Container recreated with success!");
      }

Executing runtime commands in KIE Server

  OptaPlanner supports runtime commands that you can send to KIE Server for asset-related operations, such as inserting or retracting objects in a KIE session or firing all rules. The full list of supported runtime commands is located in the `org.drools.core.command.runtime` package in your OptaPlanner instance.

  You can use the `org.kie.api.command.KieCommands` class to insert commands, and use `org.kie.api.KieServices.get().getCommands()` to instantiate the `KieCommands` class. If you want to add multiple commands, use the `BatchExecutionCommand` wrapper.

  Example request to insert an object and fire all rules

      import org.kie.api.command.Command;
      import org.kie.api.command.KieCommands;
      import org.kie.server.api.model.ServiceResponse;
      import org.kie.server.client.RuleServicesClient;
      import org.kie.server.client.KieServicesClient;
      import org.kie.api.KieServices;

      import java.util.Arrays;

      ...

      public void executeCommands() {

        String containerId = "hello";
        System.out.println("== Sending commands to the server ==");
        RuleServicesClient rulesClient = kieServicesClient.getServicesClient(RuleServicesClient.class);
        KieCommands commandsFactory = KieServices.Factory.get().getCommands();

        Command<?> insert = commandsFactory.newInsert("Some String OBJ");
        Command<?> fireAllRules = commandsFactory.newFireAllRules();
        Command<?> batchCommand = commandsFactory.newBatchExecution(Arrays.asList(insert, fireAllRules));

        ServiceResponse<String> executeResponse = rulesClient.executeCommands(containerId, batchCommand);

        if(executeResponse.getType() == ResponseType.SUCCESS) {
          System.out.println("Commands executed with success! Response: ");
          System.out.println(executeResponse.getResult());
        } else {
          System.out.println("Error executing rules. Message: ");
          System.out.println(executeResponse.getMsg());
        }
      }

  | A conversation between a client and a specific KIE Server container in a clustered environment is secured by a unique `conversationID`. The `conversationID` is transferred using the `X-KIE-ConversationId` REST header. If you update the container, unset the previous `conversationID`. Use `KieServiesClient.completeConversation()` to unset the `conversationID` for Java API.

### 7.10. KIE Server and KIE container commands in OptaPlanner

OptaPlanner supports server commands that you can send to KIE Server for server-related or container-related operations, such as retrieving server information or creating or deleting a container. The full list of supported KIE Server configuration commands is located in the `org.kie.server.api.commands` package in your OptaPlanner instance.

In the KIE Server REST API, you use the `org.kie.server.api.commands` commands as the request body for `POST` requests to `http://SERVER:PORT/kie-server/services/rest/server/config`. For more information about using the KIE Server REST API, see KIE Server REST API for KIE containers and business assets.

In the KIE Server Java client API, you use the corresponding method in the parent `KieServicesClient` Java client as an embedded API request in your Java application. All KIE Server commands are executed by methods provided in the Java client API, so you do not need to embed the actual KIE Server commands in your Java application. For more information about using the KIE Server Java client API, see KIE Server Java client API for KIE containers and business assets.

#### 7.10.1. Sample KIE Server and KIE container commands

The following are sample KIE Server commands that you can use with the KIE Server REST API or Java client API for server-related or container-related operations in KIE Server:

- `GetServerInfoCommand`

- `GetServerStateCommand`

- `CreateContainerCommand`

- `GetContainerInfoCommand`

- `ListContainersCommand`

- `CallContainerCommand`

- `DisposeContainerCommand`

- `GetScannerInfoCommand`

- `UpdateScannerCommand`

- `UpdateReleaseIdCommand`

For the full list of supported KIE Server configuration and management commands, see the `org.kie.server.api.commands` package in your OptaPlanner instance.

You can run KIE Server commands individually or together as a batch REST API request or batch Java API request:

Batch REST API request to create, call, and dispose a KIE container (JSON)

    {
      "commands": [
        {
          "create-container": {
            "container": {
              "status": "STARTED",
              "container-id": "command-script-container",
              "release-id": {
                "version": "1.0",
                "group-id": "com.redhat",
                "artifact-id": "Project1"
              }
            }
          }
        },
        {
          "call-container": {
            "payload": "{\n  \"commands\" : [ {\n    \"fire-all-rules\" : {\n      \"max\" : -1,\n      \"out-identifier\" : null\n    }\n  } ]\n}",
            "container-id": "command-script-container"
          }
        },
        {
          "dispose-container": {
            "container-id": "command-script-container"
          }
        }
      ]
    }

Batch Java API request to retrieve, dispose, and re-create a KIE container

    public void disposeAndCreateContainer() {
        System.out.println("== Disposing and creating containers ==");

        // Retrieve list of KIE containers
        List<KieContainerResource> kieContainers = kieServicesClient.listContainers().getResult().getContainers();
        if (kieContainers.size() == 0) {
            System.out.println("No containers available...");
            return;
        }

        // Dispose KIE container
        KieContainerResource container = kieContainers.get(0);
        String containerId = container.getContainerId();
        ServiceResponse<Void> responseDispose = kieServicesClient.disposeContainer(containerId);
        if (responseDispose.getType() == ResponseType.FAILURE) {
            System.out.println("Error disposing " + containerId + ". Message: ");
            System.out.println(responseDispose.getMsg());
            return;
        }
        System.out.println("Success Disposing container " + containerId);
        System.out.println("Trying to recreate the container...");

        // Re-create KIE container
        ServiceResponse<KieContainerResource> createResponse = kieServicesClient.createContainer(containerId, container);
        if(createResponse.getType() == ResponseType.FAILURE) {
            System.out.println("Error creating " + containerId + ". Message: ");
            System.out.println(responseDispose.getMsg());
            return;
        }
        System.out.println("Container recreated with success!");
    }

Each command in this section includes a REST request body example (JSON) for the KIE Server REST API and an embedded method example from the `KieServicesClient` Java client for the KIE Server Java client API.

GetServerInfoCommand

  Returns information about this KIE Server instance.

  Example REST request body (JSON)

      {
        "commands" : [ {
          "get-server-info" : { }
        } ]
      }

  Example Java client method

      KieServerInfo serverInfo = kieServicesClient.getServerInfo();

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Kie Server info",
            "result": {
              "kie-server-info": {
                "id": "default-kieserver",
                "version": "7.11.0.Final-redhat-00001",
                "name": "default-kieserver",
                "location": "http://localhost:8080/kie-server/services/rest/server",
                "capabilities": [
                  "KieServer",
                  "BRM",
                  "BPM",
                  "CaseMgmt",
                  "BPM-UI",
                  "BRP",
                  "DMN",
                  "Swagger"
                ],
                "messages": [
                  {
                    "severity": "INFO",
                    "timestamp": {
                      "java.util.Date": 1538502533321
                    },
                    "content": [
                      "Server KieServerInfo{serverId='default-kieserver', version='7.11.0.Final-redhat-00001', name='default-kieserver', location='http://localhost:8080/kie-server/services/rest/server', capabilities=[KieServer, BRM, BPM, CaseMgmt, BPM-UI, BRP, DMN, Swagger], messages=null}started successfully at Tue Oct 02 13:48:53 EDT 2018"
                    ]
                  }
                ]
              }
            }
          }
        ]
      }

GetServerStateCommand

  Returns information about the current state and configurations of this KIE Server instance.

  Example REST request body (JSON)

      {
        "commands" : [ {
          "get-server-state" : { }
        } ]
      }

  Example Java client method

      KieServerStateInfo serverStateInfo = kieServicesClient.getServerState();

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Successfully loaded server state for server id default-kieserver",
            "result": {
              "kie-server-state-info": {
                "controller": [
                  "http://localhost:8080/business-central/rest/controller"
                ],
                "config": {
                  "config-items": [
                    {
                      "itemName": "org.kie.server.location",
                      "itemValue": "http://localhost:8080/kie-server/services/rest/server",
                      "itemType": "java.lang.String"
                    },
                    {
                      "itemName": "org.kie.server.controller.user",
                      "itemValue": "controllerUser",
                      "itemType": "java.lang.String"
                    },
                    {
                      "itemName": "org.kie.server.controller",
                      "itemValue": "http://localhost:8080/business-central/rest/controller",
                      "itemType": "java.lang.String"
                    }
                  ]
                },
                "containers": [
                  {
                    "container-id": "employee-rostering",
                    "release-id": {
                      "group-id": "employeerostering",
                      "artifact-id": "employeerostering",
                      "version": "1.0.0-SNAPSHOT"
                    },
                    "resolved-release-id": null,
                    "status": "STARTED",
                    "scanner": {
                      "status": "STOPPED",
                      "poll-interval": null
                    },
                    "config-items": [
                      {
                        "itemName": "KBase",
                        "itemValue": "",
                        "itemType": "BPM"
                      },
                      {
                        "itemName": "KSession",
                        "itemValue": "",
                        "itemType": "BPM"
                      },
                      {
                        "itemName": "MergeMode",
                        "itemValue": "MERGE_COLLECTIONS",
                        "itemType": "BPM"
                      },
                      {
                        "itemName": "RuntimeStrategy",
                        "itemValue": "SINGLETON",
                        "itemType": "BPM"
                      }
                    ],
                    "messages": [],
                    "container-alias": "employeerostering"
                  }
                ]
              }
            }
          }
        ]
      }

CreateContainerCommand

  Creates a KIE container in the KIE Server.

  Table 33. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `container` | Map containing the `container-id`, `release-id` data (group ID, artifact ID, version), `status`, and any other components of the new KIE container | Required

  Example REST request body (JSON)

      {
        "commands" : [ {
          "create-container" : {
            "container" : {
              "status" : null,
              "messages" : [ ],
              "container-id" : "command-script-container",
              "release-id" : {
                "version" : "1.0",
                "group-id" : "com.redhat",
                "artifact-id" : "Project1"
              },
              "config-items" : [ ]
            }
          }
        } ]
      }

  Example Java client method

      ServiceResponse<KieContainerResource> response = kieServicesClient.createContainer("command-script-container", resource);

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully deployed with module com.redhat:Project1:1.0.",
            "result": {
              "kie-container": {
                "container-id": "command-script-container",
                "release-id": {
                  "version" : "1.0",
                  "group-id" : "com.redhat",
                  "artifact-id" : "Project1"
                },
                "resolved-release-id": {
                  "version" : "1.0",
                  "group-id" : "com.redhat",
                  "artifact-id" : "Project1"
                },
                "status": "STARTED",
                "scanner": {
                  "status": "DISPOSED",
                  "poll-interval": null
                },
                "config-items": [],
                "messages": [
                  {
                    "severity": "INFO",
                    "timestamp": {
                      "java.util.Date": 1538762455510
                    },
                    "content": [
                      "Container command-script-container successfully created with module com.redhat:Project1:1.0."
                    ]
                  }
                ],
                "container-alias": null
              }
            }
          }
        ]
      }

GetContainerInfoCommand

  Returns information about a specified KIE container in KIE Server.

  Table 34. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `container-id` | ID of the KIE container | Required

  Example REST request body (JSON)

      {
        "commands" : [ {
          "get-container-info" : {
            "container-id" : "command-script-container"
          }
        } ]
      }

  Example Java client method

      ServiceResponse<KieContainerResource> response = kieServicesClient.getContainerInfo("command-script-container");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Info for container command-script-container",
            "result": {
              "kie-container": {
                "container-id": "command-script-container",
                "release-id": {
                  "group-id": "com.redhat",
                  "artifact-id": "Project1",
                  "version": "1.0"
                },
                "resolved-release-id": {
                  "group-id": "com.redhat",
                  "artifact-id": "Project1",
                  "version": "1.0"
                },
                "status": "STARTED",
                "scanner": {
                  "status": "DISPOSED",
                  "poll-interval": null
                },
                "config-items": [

                ],
                "container-alias": null
              }
            }
          }
        ]
      }

ListContainersCommand

  Returns a list of KIE containers that have been created in this KIE Server instance.

  Table 35. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `kie-container-filter` | Optional map containing `release-id-filter`, `container-status-filter`, and any other KIE container properties by which you want to filter results | Optional

  Example REST request body (JSON)

      {
        "commands" : [ {
          "list-containers" : {
            "kie-container-filter" : {
              "release-id-filter" : { },
              "container-status-filter" : {
                "accepted-status" : ["FAILED"]
              }
            }
          }
        } ]
      }

  Example Java client method

      KieContainerResourceFilter filter = new KieContainerResourceFilter.Builder()
              .status(KieContainerStatus.FAILED)
              .build();

      KieContainerResourceList containersList = kieServicesClient.listContainers(filter);

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "List of created containers",
            "result": {
              "kie-containers": {
                "kie-container": [
                  {
                    "container-id": "command-script-container",
                    "release-id": {
                      "group-id": "com.redhat",
                      "artifact-id": "Project1",
                      "version": "1.0"
                    },
                    "resolved-release-id": {
                      "group-id": "com.redhat",
                      "artifact-id": "Project1",
                      "version": "1.0"
                    },
                    "status": "STARTED",
                    "scanner": {
                      "status": "STARTED",
                      "poll-interval": 5000
                    },
                    "config-items": [
                      {
                        "itemName": "RuntimeStrategy",
                        "itemValue": "SINGLETON",
                        "itemType": "java.lang.String"
                      },
                      {
                        "itemName": "MergeMode",
                        "itemValue": "MERGE_COLLECTIONS",
                        "itemType": "java.lang.String"
                      },
                      {
                        "itemName": "KBase",
                        "itemValue": "",
                        "itemType": "java.lang.String"
                      },
                      {
                        "itemName": "KSession",
                        "itemValue": "",
                        "itemType": "java.lang.String"
                      }
                    ],
                    "messages": [
                      {
                        "severity": "INFO",
                        "timestamp": {
                          "java.util.Date": 1538504619749
                        },
                        "content": [
                          "Container command-script-container successfully created with module com.redhat:Project1:1.0."
                        ]
                      }
                    ],
                    "container-alias": null
                  }
                ]
              }
            }
          }
        ]
      }

CallContainerCommand

  Calls a KIE container and executes one or more runtime commands. For information about OptaPlanner runtime commands, see Runtime commands in OptaPlanner.

  Table 36. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `container-id` | ID of the KIE container to be called | Required
  `payload` | One or more commands in a `BatchExecutionCommand` wrapper to be executed on the KIE container | Required

  Example REST request body (JSON)

      {
        "commands" : [ {
          "call-container" : {
            "payload" : "{\n  \"lookup\" : \"defaultKieSession\",\n  \"commands\" : [ {\n    \"fire-all-rules\" : {\n      \"max\" : -1,\n      \"out-identifier\" : null\n    }\n  } ]\n}",
            "container-id" : "command-script-container"
          }
        } ]
      }

  Example Java client method

      List<Command<?>> commands = new ArrayList<Command<?>>();
            BatchExecutionCommand batchExecution1 = commandsFactory.newBatchExecution(commands, "defaultKieSession");
            commands.add(commandsFactory.newFireAllRules());

            ServiceResponse<ExecutionResults> response1 = ruleClient.executeCommandsWithResults("command-script-container", batchExecution1);

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully called.",
            "result": "{\n  \"results\" : [ ],\n  \"facts\" : [ ]\n}"
          }
        ]
      }

DisposeContainerCommand

  Disposes a specified KIE container in the KIE Server.

  Table 37. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `container-id` | ID of the KIE container to be disposed | Required

  Example REST request body (JSON)

      {
        "commands" : [ {
          "dispose-container" : {
            "container-id" : "command-script-container"
          }
        } ]
      }

  Example Java client method

      ServiceResponse<Void> response = kieServicesClient.disposeContainer("command-script-container");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully disposed.",
            "result": null
          }
        ]
      }

GetScannerInfoCommand

  Returns information about the KIE scanner used for automatic updates in a specified KIE container, if applicable.

  Table 38. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `container-id` | ID of the KIE container where the KIE scanner is used | Required

  Example REST request body (JSON)

      {
        "commands" : [ {
          "get-scanner-info" : {
            "container-id" : "command-script-container"
          }
        } ]
      }

  Example Java client method

      ServiceResponse<KieScannerResource> response = kieServicesClient.getScannerInfo("command-script-container");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Scanner info successfully retrieved",
            "result": {
              "kie-scanner": {
                "status": "DISPOSED",
                "poll-interval": null
              }
            }
          }
        ]
      }

UpdateScannerCommand

  Starts or stops a KIE scanner that controls polling for updated KIE container deployments.

  | Avoid using a KIE scanner with business processes. Using a KIE scanner with processes can lead to unforeseen updates that can then cause errors in long-running processes when changes are not compatible with running process instances.

  Table 39. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `container-id` | ID of the KIE container where the KIE scanner is used | Required
  `status` | Status to be set on the KIE scanner (`STARTED`, `STOPPED`) | Required
  `poll-interval` | Permitted polling duration in milliseconds | Required only when starting scanner

  Example REST request body (JSON)

      {
        "commands" : [ {
          "update-scanner" : {
            "scanner" : {
              "status" : "STARTED",
              "poll-interval" : 10000
            },
            "container-id" : "command-script-container"
          }
        } ]
      }

  Example Java client method

      KieScannerResource scannerResource = new KieScannerResource();
      scannerResource.setPollInterval(10000);
      scannerResource.setStatus(KieScannerStatus. STARTED);

      ServiceResponse<KieScannerResource> response = kieServicesClient.updateScanner("command-script-container", scannerResource);

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Kie scanner successfully created.",
            "result": {
              "kie-scanner": {
                "status": "STARTED",
                "poll-interval": 10000
              }
            }
          }
        ]
      }

UpdateReleaseIdCommand

  Updates the release ID data (group ID, artifact ID, version) for a specified KIE container.

  Table 40. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `container-id` | ID of the KIE container to be updated | Required
  `releaseId` | Updated GAV (group ID, artifact ID, version) data to be applied to the KIE container | Required

  Example REST request body (JSON)

      {
        "commands" : [ {
          "update-release-id" : {
            "releaseId" : {
              "version" : "1.1",
              "group-id" : "com.redhat",
              "artifact-id" : "Project1"
            },
            "container-id" : "command-script-container"
          }
        } ]
      }

  Example Java client method

      ServiceResponse<ReleaseId> response = kieServicesClient.updateReleaseId("command-script-container", "com.redhat:Project1:1.1");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Release id successfully updated",
            "result": {
              "release-id": {
                "group-id": "com.redhat",
                "artifact-id": "Project1",
                "version": "1.1"
              }
            }
          }
        ]
      }

### 7.11. Runtime commands in OptaPlanner

OptaPlanner supports runtime commands that you can send to KIE Server for asset-related operations, such as executing all rules or inserting or retracting objects in a KIE session. The full list of supported runtime commands is located in the `org.drools.core.command.runtime` package in your OptaPlanner instance.

In the KIE Server REST API, you use the global `org.drools.core.command.runtime` commands or the rule-specific `org.drools.core.command.runtime.rule` commands as the request body for `POST` requests to `http://SERVER:PORT/kie-server/services/rest/server/containers/instances/{containerId}`. For more information about using the KIE Server REST API, see KIE Server REST API for KIE containers and business assets.

In the KIE Server Java client API, you can embed these commands in your Java application along with the relevant Java client. For example, for rule-related commands, you use the `RuleServicesClient` Java client with the embedded commands. For more information about using the KIE Server Java client API, see KIE Server Java client API for KIE containers and business assets.

#### 7.11.1. Sample runtime commands in OptaPlanner

The following are sample runtime commands that you can use with the KIE Server REST API or Java client API for asset-related operations in KIE Server:

- `BatchExecutionCommand`

- `InsertObjectCommand`

- `RetractCommand`

- `ModifyCommand`

- `GetObjectCommand`

- `GetObjectsCommand`

- `InsertElementsCommand`

- `FireAllRulesCommand`

- `QueryCommand`

- `SetGlobalCommand`

- `GetGlobalCommand`

For the full list of supported runtime commands, see the `org.drools.core.command.runtime` package in your OptaPlanner instance.

Each command in this section includes a REST request body example (JSON) for the KIE Server REST API and an embedded Java command example for the KIE Server Java client API. The Java examples use an object `org.drools.compiler.test.Person` with the fields `name` (String) and `age` (Integer).

BatchExecutionCommand

  Contains multiple commands to be executed together.

  Table 41. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `commands` | List of commands to be executed. | Required
  `lookup` | Sets the KIE session ID on which the commands will be executed. For stateless KIE sessions, this attribute is required. For stateful KIE sessions, this attribute is optional and if not specified, the default KIE session is used. | Required for stateless KIE session, optional for stateful KIE session

  | KIE session IDs are in the `kmodule.xml` file of your OptaPlanner project. To view or add a KIE session ID in Business Central to use with the `lookup` command attribute, navigate to the relevant project in Business Central and go to project Settings → KIE bases → KIE sessions. If no KIE bases exist, click Add KIE base → KIE sessions to define the new KIE base and KIE sessions.

  Example JSON request body

      {
        "lookup": "ksession1",
        "commands": [ {
            "insert": {
              "object": {
                "org.drools.compiler.test.Person": {
                  "name": "john",
                  "age": 25
                }
              }
            }
          },
          {
            "fire-all-rules": {
              "max": 10,
              "out-identifier": "firedActivations"
            }
          }
        ]
      }

  Example Java command

      InsertObjectCommand insertCommand = new InsertObjectCommand(new Person("john", 25));
      FireAllRulesCommand fireCommand = new FireAllRulesCommand();

      BatchExecutionCommand batch = new BatchExecutionCommandImpl(Arrays.asList(insertCommand, fireCommand), "ksession1");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully called.",
            "result": {
              "execution-results": {
                "results": [
                  {
                    "value": 0,
                    "key": "firedActivations"
                  }
                ],
                "facts": []
              }
            }
          }
        ]
      }

InsertObjectCommand

  Inserts an object into the KIE session.

  Table 42. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `object` | The object to be inserted | Required
  `out-identifier` | ID of the `FactHandle` created from the object insertion and added to the execution results | Optional
  `return-object` | Boolean to determine whether the object must be returned in the execution results (default: `true`) | Optional
  `entry-point` | Entry point for the insertion | Optional

  Example JSON request body

      {
        "commands": [ {
            "insert": {
              "entry-point": "my stream",
              "object": {
                "org.drools.compiler.test.Person": {
                  "age": 25,
                  "name": "john"
                }
              },
              "out-identifier": "john",
              "return-object": false
            }
          }
        ]
      }

  Example Java command

      Command insertObjectCommand =
        CommandFactory.newInsert(new Person("john", 25), "john", false, null);

      ksession.execute(insertObjectCommand);

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully called.",
            "result": {
              "execution-results": {
                "results": [],
                "facts": [
                  {
                    "value": {
                      "org.drools.core.common.DefaultFactHandle": {
                        "external-form": "0:4:436792766:-2127720265:4:DEFAULT:NON_TRAIT:java.util.LinkedHashMap"
                      }
                    },
                    "key": "john"
                  }
                ]
              }
            }
          }
        ]
      }

RetractCommand

  Retracts an object from the KIE session.

  Table 43. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `fact-handle` | The `FactHandle` associated with the object to be retracted | Required

  Example JSON request body

      {
        "commands": [ {
            "retract": {
              "fact-handle": "0:4:436792766:-2127720265:4:DEFAULT:NON_TRAIT:java.util.LinkedHashMap"
            }
          }
        ]
      }

  Example Java command: Use `FactHandleFromString`

      RetractCommand retractCommand = new RetractCommand();
      retractCommand.setFactHandleFromString("123:234:345:456:567");

  Example Java command: Use `FactHandle` from inserted object

      RetractCommand retractCommand = new RetractCommand(factHandle);

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container employee-rostering successfully called.",
            "result": {
              "execution-results": {
                "results": [],
                "facts": []
              }
            }
          }
        ]
      }

ModifyCommand

  Modifies a previously inserted object in the KIE session.

  Table 44. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `fact-handle` | The `FactHandle` associated with the object to be modified | Required
  `setters` | List of setters for object modifications | Required

  Example JSON request body

      {
        "commands": [ {
            "modify": {
              "fact-handle": "0:4:436792766:-2127720265:4:DEFAULT:NON_TRAIT:java.util.LinkedHashMap",
              "setters": {
                "accessor": "age",
                "value": 25
              }
            }
          }
        ]
      }

  Example Java command

      ModifyCommand modifyCommand = new ModifyCommand(factHandle);

      List<Setter> setters = new ArrayList<Setter>();
      setters.add(new SetterImpl("age", "25"));

      modifyCommand.setSetters(setters);

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container employee-rostering successfully called.",
            "result": {
              "execution-results": {
                "results": [],
                "facts": []
              }
            }
          }
        ]
      }

GetObjectCommand

  Retrieves an object from a KIE session.

  Table 45. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `fact-handle` | The `FactHandle` associated with the object to be retrieved | Required
  `out-identifier` | ID of the `FactHandle` created from the object insertion and added to the execution results | Optional

  Example JSON request body

      {
        "commands": [ {
            "get-object": {
              "fact-handle": "0:4:436792766:-2127720265:4:DEFAULT:NON_TRAIT:java.util.LinkedHashMap",
              "out-identifier": "john"
            }
          }
        ]
      }

  Example Java command

      GetObjectCommand getObjectCommand = new GetObjectCommand();
      getObjectCommand.setFactHandleFromString("123:234:345:456:567");
      getObjectCommand.setOutIdentifier("john");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully called.",
            "result": {
              "execution-results": {
                "results": [
                  {
                    "value": null,
                    "key": "john"
                  }
                ],
                "facts": []
              }
            }
          }
        ]
      }

GetObjectsCommand

  Retrieves all objects from the KIE session as a collection.

  Table 46. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `object-filter` | Filter for the objects returned from the KIE session | Optional
  `out-identifier` | Identifier to be used in the execution results | Optional

  Example JSON request body

      {
        "commands": [ {
            "get-objects": {
              "out-identifier": "objects"
            }
          }
        ]
      }

  Example Java command

      GetObjectsCommand getObjectsCommand = new GetObjectsCommand();
      getObjectsCommand.setOutIdentifier("objects");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully called.",
            "result": {
              "execution-results": {
                "results": [
                  {
                    "value": [
                      {
                        "org.apache.xerces.dom.ElementNSImpl": "<?xml version=\"1.0\" encoding=\"UTF-16\"?>\n<object xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"person\"><age>25</age><name>john</name>\n <\/object>"
                      },
                      {
                        "org.drools.compiler.test.Person": {
                          "name": "john",
                          "age": 25
                        }
                      }
                    ],
                    "key": "objects"
                  }
                ],
                "facts": []
              }
            }
          }
        ]
      }

InsertElementsCommand

  Inserts a list of objects into the KIE session.

  Table 47. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `objects` | The list of objects to be inserted into the KIE session | Required
  `out-identifier` | ID of the `FactHandle` created from the object insertion and added to the execution results | Optional
  `return-object` | Boolean to determine whether the object must be returned in the execution results. Default value: `true`. | Optional
  `entry-point` | Entry point for the insertion | Optional

  Example JSON request body

      {
        "commands": [ {
          "insert-elements": {
              "objects": [
                  {
                      "containedObject": {
                          "@class": "org.drools.compiler.test.Person",
                          "age": 25,
                          "name": "john"
                      }
                  },
                  {
                      "containedObject": {
                          "@class": "Person",
                          "age": 35,
                          "name": "sarah"
                      }
                  }
              ]
          }
        }
      ]
      }

  Example Java command

      List<Object> objects = new ArrayList<Object>();
      objects.add(new Person("john", 25));
      objects.add(new Person("sarah", 35));

      Command insertElementsCommand = CommandFactory.newInsertElements(objects);

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully called.",
            "result": {
              "execution-results": {
                "results": [],
                "facts": [
                  {
                    "value": {
                      "org.drools.core.common.DefaultFactHandle": {
                        "external-form": "0:4:436792766:-2127720265:4:DEFAULT:NON_TRAIT:java.util.LinkedHashMap"
                      }
                    },
                    "key": "john"
                  },
                  {
                    "value": {
                      "org.drools.core.common.DefaultFactHandle": {
                        "external-form": "0:4:436792766:-2127720266:4:DEFAULT:NON_TRAIT:java.util.LinkedHashMap"
                      }
                    },
                    "key": "sarah"
                  }
                ]
              }
            }
          }
        ]
      }

FireAllRulesCommand

  Executes all rules in the KIE session.

  Table 48. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `max` | Maximum number of rules to be executed. The default is `-1` and does not put any restriction on execution. | Optional
  `out-identifier` | ID to be used for retrieving the number of fired rules in execution results. | Optional
  `agenda-filter` | Agenda Filter to be used for rule execution. | Optional

  Example JSON request body

      {
        "commands" : [ {
          "fire-all-rules": {
              "max": 10,
              "out-identifier": "firedActivations"
          }
        } ]
      }

  Example Java command

      FireAllRulesCommand fireAllRulesCommand = new FireAllRulesCommand();
      fireAllRulesCommand.setMax(10);
      fireAllRulesCommand.setOutIdentifier("firedActivations");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully called.",
            "result": {
              "execution-results": {
                "results": [
                  {
                    "value": 0,
                    "key": "firedActivations"
                  }
                ],
                "facts": []
              }
            }
          }
        ]
      }

QueryCommand

  Executes a query defined in the KIE base.

  Table 49. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `name` | Query name. | Required
  `out-identifier` | ID of the query results. The query results are added in the execution results with this identifier. | Optional
  `arguments` | List of objects to be passed as a query parameter. | Optional

  Example JSON request body

      {
        "commands": [
          {
            "query": {
              "name": "persons",
              "arguments": [],
              "out-identifier": "persons"
            }
          }
        ]
      }

  Example Java command

      QueryCommand queryCommand = new QueryCommand();
      queryCommand.setName("persons");
      queryCommand.setOutIdentifier("persons");

  Example server response (JSON)

      {
        "type": "SUCCESS",
        "msg": "Container stateful-session successfully called.",
        "result": {
          "execution-results": {
            "results": [
              {
                "value": {
                  "org.drools.core.runtime.rule.impl.FlatQueryResults": {
                    "idFactHandleMaps": {
                      "type": "LIST",
                      "componentType": null,
                      "element": [
                        {
                          "type": "MAP",
                          "componentType": null,
                          "element": [
                            {
                              "value": {
                                "org.drools.core.common.DisconnectedFactHandle": {
                                  "id": 1,
                                  "identityHashCode": 1809949690,
                                  "objectHashCode": 1809949690,
                                  "recency": 1,
                                  "object": {
                                    "org.kie.server.testing.Person": {
                                      "fullname": "John Doe",
                                      "age": 47
                                    }
                                  },
                                  "entryPointId": "DEFAULT",
                                  "traitType": "NON_TRAIT",
                                  "external-form": "0:1:1809949690:1809949690:1:DEFAULT:NON_TRAIT:org.kie.server.testing.Person"
                                }
                              },
                              "key": "$person"
                            }
                          ]
                        }
                      ]
                    },
                    "idResultMaps": {
                      "type": "LIST",
                      "componentType": null,
                      "element": [
                        {
                          "type": "MAP",
                          "componentType": null,
                          "element": [
                            {
                              "value": {
                                "org.kie.server.testing.Person": {
                                  "fullname": "John Doe",
                                  "age": 47
                                }
                              },
                              "key": "$person"
                            }
                          ]
                        }
                      ]
                    },
                    "identifiers": {
                      "type": "SET",
                      "componentType": null,
                      "element": [
                        "$person"
                      ]
                    }
                  }
                },
                "key": "persons"
              }
            ],
            "facts": []
          }
        }
      }

SetGlobalCommand

  Sets an object to a global state.

  Table 50. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `identifier` | ID of the global variable defined in the KIE base | Required
  `object` | Object to be set into the global variable | Optional
  `out` | Boolean to exclude the global variable you set from the execution results | Optional
  `out-identifier` | ID of the global execution result | Optional

  Example JSON request body

      {
        "commands": [
          {
            "set-global": {
              "identifier": "helper",
              "object": {
                "org.kie.server.testing.Person": {
                  "fullname": "kyle",
                  "age": 30
                }
              },
              "out-identifier": "output"
            }
          }
        ]
      }

  Example Java command

      SetGlobalCommand setGlobalCommand = new SetGlobalCommand();
      setGlobalCommand.setIdentifier("helper");
      setGlobalCommand.setObject(new Person("kyle", 30));
      setGlobalCommand.setOut(true);
      setGlobalCommand.setOutIdentifier("output");

  Example server response (JSON)

      {
        "type": "SUCCESS",
        "msg": "Container stateful-session successfully called.",
        "result": {
          "execution-results": {
            "results": [
              {
                "value": {
                  "org.kie.server.testing.Person": {
                    "fullname": "kyle",
                    "age": 30
                  }
                },
                "key": "output"
              }
            ],
            "facts": []
          }
        }
      }

GetGlobalCommand

  Retrieves a previously defined global object.

  Table 51. Command attributes
  Name | Description | Requirement
  --- | --- | ---
  `identifier` | ID of the global variable defined in the KIE base | Required
  `out-identifier` | ID to be used in the execution results | Optional

  Example JSON request body

      {
        "commands": [ {
            "get-global": {
              "identifier": "helper",
              "out-identifier": "helperOutput"
            }
          }
        ]
      }

  Example Java command

      GetGlobalCommand getGlobalCommand = new GetGlobalCommand();
      getGlobalCommand.setIdentifier("helper");
      getGlobalCommand.setOutIdentifier("helperOutput");

  Example server response (JSON)

      {
        "response": [
          {
            "type": "SUCCESS",
            "msg": "Container command-script-container successfully called.",
            "result": {
              "execution-results": {
                "results": [
                  {
                    "value": null,
                    "key": "helperOutput"
                  }
                ],
                "facts": []
              }
            }
          }
        ]
      }

### 7.12. KIE Server controller REST API for KIE Server templates and instances

OptaPlanner provides a KIE Server controller REST API that you can use to interact with your KIE Server templates (configurations), KIE Server instances (remote servers), and associated KIE containers (deployment units) in OptaPlanner without using the Business Central user interface. This API support enables you to maintain your OptaPlanner servers and resources more efficiently and optimize your integration and development with OptaPlanner.

With the KIE Server controller REST API, you can perform the following actions:

- Retrieve information about KIE Server templates, instances, and associated KIE containers

- Update, start, or stop KIE containers associated with KIE Server templates and instances

- Create, update, or delete KIE Server templates

- Create, update, or delete KIE Server instances

Requests to the KIE Server controller REST API require the following components:

Authentication

  The KIE Server controller REST API requires HTTP Basic authentication or token-based authentication for the following user roles, depending on controller type:

  - `rest-all` user role if you installed Business Central and you want to use the built-in KIE Server controller

  - `kie-server` user role if you installed the headless KIE Server controller separately from Business Central

  To view configured user roles for your OptaPlanner distribution, navigate to `~/$SERVER_HOME/standalone/configuration/application-roles.properties` and `~/application-users.properties`.

  To add a user with the `kie-server` role or the `rest-all` role or both, navigate to `~/$SERVER_HOME/bin` and run the following command with the role or roles specified:

      $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['kie-server','rest-all'])"

  To configure the `kie-server` or `rest-all` user with KIE Server controller access, navigate to `~/$SERVER_HOME/standalone/configuration/standalone-full.xml`, uncomment the `org.kie.server` properties (if applicable), and add the controller user login credentials and controller location (if needed):

      <property name="org.kie.server.location" value="http://localhost:8080/kie-server/services/rest/server"/>
      <property name="org.kie.server.controller" value="http://localhost:8080/business-central/rest/controller"/>
      <property name="org.kie.server.controller.user" value="baAdmin"/>
      <property name="org.kie.server.controller.pwd" value="password@1"/>
      <property name="org.kie.server.id" value="default-kieserver"/>

  For more information about user roles and OptaPlanner installation options, see

HTTP headers

  The KIE Server controller REST API requires the following HTTP headers for API requests:

  - `Accept`: Data format accepted by your requesting client:

    - `application/json` (JSON)

    - `application/xml` (XML, for JAXB)

  - `Content-Type`: Data format of your `POST` or `PUT` API request data:

    - `application/json` (JSON)

    - `application/xml` (XML, for JAXB)

HTTP methods

  The KIE Server controller REST API supports the following HTTP methods for API requests:

  - `GET`: Retrieves specified information from a specified resource endpoint

  - `POST`: Updates a resource or resource instance

  - `PUT`: Creates a resource or resource instance

  - `DELETE`: Deletes a resource or resource instance

Base URL

  The base URL for KIE Server controller REST API requests is `http://SERVER:PORT/CONTROLLER/rest/`, such as `http://localhost:8080/business-central/rest/` if you are using the KIE Server controller built in to Business Central.

Endpoints

  KIE Server controller REST API endpoints, such as `/controller/management/servers/{serverTemplateId}` for a specified KIE Server template, are the URIs that you append to the KIE Server controller REST API base URL to access the corresponding server resource or type of server resource in OptaPlanner.

  Example request URL for `/controller/management/servers/{serverTemplateId}` endpoint

  `http://localhost:8080/business-central/rest/controller/management/servers/default-kieserver`

Request parameters and request data

  Some KIE Server controller REST API requests require specific parameters in the request URL path to identify or filter specific resources and to perform specific actions. You can append URL parameters to the endpoint in the format `?<PARAM>=<VALUE>&<PARAM>=<VALUE>`.

  Example DELETE request URL with parameters

  `http://localhost:8080/business-central/rest/controller/server/new-kieserver-instance?location=http://localhost:8080/kie-server/services/rest/server`

  HTTP `POST` and `PUT` requests may additionally require a request body or file with data to accompany the request.

  Example PUT request URL and JSON request body data

  `http://localhost:8080/business-central/rest/controller/management/servers/new-kieserver`

      {
        "server-id": "new-kieserver",
        "server-name": "new-kieserver",
        "container-specs": [],
        "server-config": {},
        "capabilities": [
          "RULE",
          "PROCESS",
          "PLANNING"
        ]
      }

#### 7.12.1. Sending requests with the KIE Server controller REST API using a REST client or curl utility

The KIE Server controller REST API enables you to interact with your KIE Server templates (configurations), KIE Server instances (remote servers), and associated KIE containers (deployment units) in OptaPlanner without using the Business Central user interface. You can send KIE Server controller REST API requests using any REST client or curl utility.

Prerequisites

- KIE Server is installed and running.

- The KIE Server controller or headless KIE Server controller is installed and running.

- You have `rest-all` user role access to the KIE Server controller if you installed Business Central, or `kie-server` user role access to the headless KIE Server controller installed separately from Business Central.

Procedure

1. Identify the relevant API endpoint to which you want to send a request, such as `[GET] /controller/management/servers` to retrieve KIE Server templates from the KIE Server controller.

2. In a REST client or curl utility, enter the following components for a `GET` request to `controller/management/servers`. Adjust any request details according to your use case.

   For REST client:

   - Authentication: Enter the user name and password of the KIE Server controller user with the `rest-all` role or the headless KIE Server controller user with the `kie-server` role.

   - HTTP Headers: Set the following header:

     - `Accept`: `application/json`

   - HTTP method: Set to `GET`.

   - URL: Enter the KIE Server controller REST API base URL and endpoint, such as `http://localhost:8080/business-central/rest/controller/management/servers`.

   For curl utility:

   - `-u`: Enter the user name and password of the KIE Server controller user with the `rest-all` role or the headless KIE Server controller user with the `kie-server` role.

   - `-H`: Set the following header:

     - `Accept`: `application/json`

   - `-X`: Set to `GET`.

   - URL: Enter the KIE Server controller REST API base URL and endpoint, such as `http://localhost:8080/business-central/rest/controller/management/servers`.

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -X GET "http://localhost:8080/business-central/rest/controller/management/servers"

3. Execute the request and review the KIE Server controller response.

   Example server response (JSON):

       {
         "server-template": [
           {
             "server-id": "default-kieserver",
             "server-name": "default-kieserver",
             "container-specs": [
               {
                 "container-id": "employeerostering_1.0.0-SNAPSHOT",
                 "container-name": "employeerostering",
                 "server-template-key": {
                   "server-id": "default-kieserver",
                   "server-name": "default-kieserver"
                 },
                 "release-id": {
                   "group-id": "employeerostering",
                   "artifact-id": "employeerostering",
                   "version": "1.0.0-SNAPSHOT"
                 },
                 "configuration": {
                   "RULE": {
                     "org.kie.server.controller.api.model.spec.RuleConfig": {
                       "pollInterval": null,
                       "scannerStatus": "STOPPED"
                     }
                   },
                   "PROCESS": {
                     "org.kie.server.controller.api.model.spec.ProcessConfig": {
                       "runtimeStrategy": "SINGLETON",
                       "kbase": "",
                       "ksession": "",
                       "mergeMode": "MERGE_COLLECTIONS"
                     }
                   }
                 },
                 "status": "STARTED"
               },
               {
                 "container-id": "mortgage-process_1.0.0-SNAPSHOT",
                 "container-name": "mortgage-process",
                 "server-template-key": {
                   "server-id": "default-kieserver",
                   "server-name": "default-kieserver"
                 },
                 "release-id": {
                   "group-id": "mortgage-process",
                   "artifact-id": "mortgage-process",
                   "version": "1.0.0-SNAPSHOT"
                 },
                 "configuration": {
                   "RULE": {
                     "org.kie.server.controller.api.model.spec.RuleConfig": {
                       "pollInterval": null,
                       "scannerStatus": "STOPPED"
                     }
                   },
                   "PROCESS": {
                     "org.kie.server.controller.api.model.spec.ProcessConfig": {
                       "runtimeStrategy": "PER_PROCESS_INSTANCE",
                       "kbase": "",
                       "ksession": "",
                       "mergeMode": "MERGE_COLLECTIONS"
                     }
                   }
                 },
                 "status": "STARTED"
               }
             ],
             "server-config": {},
             "server-instances": [
               {
                 "server-instance-id": "default-kieserver-instance@localhost:8080",
                 "server-name": "default-kieserver-instance@localhost:8080",
                 "server-template-id": "default-kieserver",
                 "server-url": "http://localhost:8080/kie-server/services/rest/server"
               }
             ],
             "capabilities": [
               "RULE",
               "PROCESS",
               "PLANNING"
             ]
           }
         ]
       }

4. In your REST client or curl utility, send another API request with the following components for a `PUT` request to `/controller/management/servers/{serverTemplateId}` to create a new KIE Server template. Adjust any request details according to your use case.

   For REST client:

   - Authentication: Enter the user name and password of the KIE Server controller user with the `rest-all` role or the headless KIE Server controller user with the `kie-server` role.

   - HTTP Headers: Set the following headers:

     - `Accept`: `application/json`

     - `Content-Type`: `application/json`

   - HTTP method: Set to `PUT`.

   - URL: Enter the KIE Server controller REST API base URL and endpoint, such as `http://localhost:8080/business-central/rest/controller/management/servers/new-kieserver`.

   - Request body: Add a JSON request body with the configurations for the new KIE Server template:

       {
         "server-id": "new-kieserver",
         "server-name": "new-kieserver",
         "container-specs": [],
         "server-config": {},
         "capabilities": [
           "RULE",
           "PROCESS",
           "PLANNING"
         ]
       }

   For curl utility:

   - `-u`: Enter the user name and password of the KIE Server controller user with the `rest-all` role or the headless KIE Server controller user with the `kie-server` role.

   - `-H`: Set the following headers:

     - `Accept`: `application/json`

     - `Content-Type`: `application/json`

   - `-X`: Set to `PUT`.

   - URL: Enter the KIE Server controller REST API base URL and endpoint, such as `http://localhost:8080/business-central/rest/controller/management/servers/new-kieserver`.

   - `-d`: Add a JSON request body or file (`@file.json`) with the configurations for the new KIE Server template:

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -H "Content-Type: application/json" -X PUT "http://localhost:8080/business-central/rest/controller/management/servers/new-kieserver" -d "{ \"server-id\": \"new-kieserver\", \"server-name\": \"new-kieserver\", \"container-specs\": [], \"server-config\": {}, \"capabilities\": [ \"RULE\", \"PROCESS\", \"PLANNING\" ]}"

       curl -u 'baAdmin:password@1' -H "Accept: application/json" -H "Content-Type: application/json" -X PUT "http://localhost:8080/business-central/rest/controller/management/servers/new-kieserver" -d @my-server-template-configs.json

5. Execute the request and confirm the successful KIE Server controller response.

   If you encounter request errors, review the returned error code messages and adjust your request accordingly.

#### 7.12.2. Sending requests with the KIE Server controller REST API using the Swagger interface

The KIE Server controller REST API supports a Swagger web interface that you can use instead of a standalone REST client or curl utility to interact with your KIE Server templates, instances, and associated KIE containers in OptaPlanner without using the Business Central user interface.

| By default, the Swagger web interface for the KIE Server controller is enabled by the `org.kie.workbench.swagger.disabled=false` system property. To disable the Swagger web interface for the KIE Server controller, set this system property to `true`.

Prerequisites

- The KIE Server controller is installed and running.

- You have `rest-all` user role access to the KIE Server controller if you installed Business Central, or `kie-server` user role access to the headless KIE Server controller installed separately from Business Central.

Procedure

1. In a web browser, navigate to `http://SERVER:PORT/CONTROLLER/docs`, such as `http://localhost:8080/business-central/docs`, and log in with the user name and password of the KIE Server controller user with the `rest-all` role or the headless KIE Server controller user with the `kie-server` role.

   | If you are using the KIE Server controller built in to Business Central, the Swagger page associated with the KIE Server controller is identified as the "Business Central API" for Business Central REST services. If you are using the headless KIE Server controller without Business Central, the Swagger page associated with the headless KIE Server controller is identified as the "Controller API". In both cases, the KIE Server controller REST API endpoints are the same.

2. In the Swagger page, select the relevant API endpoint to which you want to send a request, such as Controller :: KIE Server templates and KIE containers → [GET] /controller/management/servers to retrieve KIE Server templates from the KIE Server controller.

3. Click Try it out and provide any optional parameters by which you want to filter results, if applicable.

4. In the Response content type drop-down menu, select the desired format of the server response, such as application/json for JSON format.

5. Click Execute and review the KIE Server response.

   Example server response (JSON):

       {
         "server-template": [
           {
             "server-id": "default-kieserver",
             "server-name": "default-kieserver",
             "container-specs": [
               {
                 "container-id": "employeerostering_1.0.0-SNAPSHOT",
                 "container-name": "employeerostering",
                 "server-template-key": {
                   "server-id": "default-kieserver",
                   "server-name": "default-kieserver"
                 },
                 "release-id": {
                   "group-id": "employeerostering",
                   "artifact-id": "employeerostering",
                   "version": "1.0.0-SNAPSHOT"
                 },
                 "configuration": {
                   "RULE": {
                     "org.kie.server.controller.api.model.spec.RuleConfig": {
                       "pollInterval": null,
                       "scannerStatus": "STOPPED"
                     }
                   },
                   "PROCESS": {
                     "org.kie.server.controller.api.model.spec.ProcessConfig": {
                       "runtimeStrategy": "SINGLETON",
                       "kbase": "",
                       "ksession": "",
                       "mergeMode": "MERGE_COLLECTIONS"
                     }
                   }
                 },
                 "status": "STARTED"
               },
               {
                 "container-id": "mortgage-process_1.0.0-SNAPSHOT",
                 "container-name": "mortgage-process",
                 "server-template-key": {
                   "server-id": "default-kieserver",
                   "server-name": "default-kieserver"
                 },
                 "release-id": {
                   "group-id": "mortgage-process",
                   "artifact-id": "mortgage-process",
                   "version": "1.0.0-SNAPSHOT"
                 },
                 "configuration": {
                   "RULE": {
                     "org.kie.server.controller.api.model.spec.RuleConfig": {
                       "pollInterval": null,
                       "scannerStatus": "STOPPED"
                     }
                   },
                   "PROCESS": {
                     "org.kie.server.controller.api.model.spec.ProcessConfig": {
                       "runtimeStrategy": "PER_PROCESS_INSTANCE",
                       "kbase": "",
                       "ksession": "",
                       "mergeMode": "MERGE_COLLECTIONS"
                     }
                   }
                 },
                 "status": "STARTED"
               }
             ],
             "server-config": {},
             "server-instances": [
               {
                 "server-instance-id": "default-kieserver-instance@localhost:8080",
                 "server-name": "default-kieserver-instance@localhost:8080",
                 "server-template-id": "default-kieserver",
                 "server-url": "http://localhost:8080/kie-server/services/rest/server"
               }
             ],
             "capabilities": [
               "RULE",
               "PROCESS",
               "PLANNING"
             ]
           }
         ]
       }

6. In the Swagger page, navigate to the Controller :: KIE Server templates and KIE containers → [GET] /controller/management/servers/{serverTemplateId} endpoint to send another request to create a new KIE Server template. Adjust any request details according to your use case.

7. Click Try it out and enter the following components for the request:

   - serverTemplateId: Enter the ID of the new KIE Server template, such as `new-kieserver`.

   - body: Set the Parameter content type to the desired request body format, such as application/json for JSON format, and add a request body with the configurations for the new KIE Server template:

       {
         "server-id": "new-kieserver",
         "server-name": "new-kieserver",
         "container-specs": [],
         "server-config": {},
         "capabilities": [
           "RULE",
           "PROCESS",
           "PLANNING"
         ]
       }

8. In the Response content type drop-down menu, select the desired format of the server response, such as application/json for JSON format.

9. Click Execute and confirm the successful KIE Server controller response.

   If you encounter request errors, review the returned error code messages and adjust your request accordingly.

#### 7.12.3. Supported KIE Server controller REST API endpoints

The KIE Server controller REST API provides endpoints for interacting with KIE Server templates (configurations), KIE Server instances (remote servers), and associated KIE containers (deployment units). The KIE Server controller REST API base URL is `http://SERVER:PORT/CONTROLLER/rest/`. All requests require HTTP Basic authentication or token-based authentication for the `rest-all` user role if you installed Business Central and you want to use the built-in KIE Server controller, or the `kie-server` user role if you installed the headless KIE Server controller separately from Business Central.

For the full list of KIE Server controller REST API endpoints and descriptions, use one of the following resources:

- Controller REST API on the jBPM Documentation page (static)

- Swagger UI for the KIE Server controller REST API at `http://SERVER:PORT/CONTROLLER/docs` (dynamic, requires running KIE Server controller)

  | By default, the Swagger web interface for the KIE Server controller is enabled by the `org.kie.workbench.swagger.disabled=false` system property. To disable the Swagger web interface for the KIE Server controller, set this system property to `true`. If you are using the KIE Server controller built in to Business Central, the Swagger page associated with the KIE Server controller is identified as the "Business Central API" for Business Central REST services. If you are using the headless KIE Server controller without Business Central, the Swagger page associated with the headless KIE Server controller is identified as the "Controller API". In both cases, the KIE Server controller REST API endpoints are the same.

### 7.13. KIE Server controller Java client API for KIE Server templates and instances

OptaPlanner provides a KIE Server controller Java client API that enables you to connect to the KIE Server controller using REST or WebSocket protocol from your Java client application. You can use the KIE Server controller Java client API as an alternative to the KIE Server controller REST API to interact with your KIE Server templates (configurations), KIE Server instances (remote servers), and associated KIE containers (deployment units) in OptaPlanner without using the Business Central user interface. This API support enables you to maintain your OptaPlanner servers and resources more efficiently and optimize your integration and development with OptaPlanner.

With the KIE Server controller Java client API, you can perform the following actions also supported by the KIE Server controller REST API:

- Retrieve information about KIE Server templates, instances, and associated KIE containers

- Update, start, or stop KIE containers associated with KIE Server templates and instances

- Create, update, or delete KIE Server templates

- Create, update, or delete KIE Server instances

KIE Server controller Java client API requests require the following components:

Authentication

  The KIE Server controller Java client API requires HTTP Basic authentication for the following user roles, depending on controller type:

  - `rest-all` user role if you installed Business Central and you want to use the built-in KIE Server controller

  - `kie-server` user role if you installed the headless KIE Server controller separately from Business Central

  To view configured user roles for your OptaPlanner distribution, navigate to `~/$SERVER_HOME/standalone/configuration/application-roles.properties` and `~/application-users.properties`.

  To add a user with the `kie-server` role or the `rest-all` role or both (assuming a Keystore is already set), navigate to `~/$SERVER_HOME/bin` and run the following command with the role or roles specified:

      $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=<USERNAME>),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=<USERNAME>, clear={password='<PASSWORD>'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=<USERNAME>, name=role, value=['rest-all','kie-server'])"

  In case the Keystore is not set, then execute the following command to create a Keystore:

      $ keytool -importpassword -keystore $SERVER_HOME/standalone/configuration/kie_keystore.jceks -keypass <SECRETKEYPASSWORD> -alias kieserver -storepass <SECRETSTOREPASSWORD> -storetype JCEKS

  Also, add the following properties to `~/$SERVER_HOME/standalone/configuration/standalone-full.xml`:

          <property name="kie.keystore.keyStoreURL" value="file:///data/jboss/rhpam780/standalone/configuration/kie_keystore.jceks"/>
          <property name="kie.keystore.keyStorePwd" value="<SECRETSTOREPASSWORD>"/>
          <property name="kie.keystore.key.server.alias" value="kieserver"/>
          <property name="kie.keystore.key.server.pwd" value="<SECRETKEYPASSWORD>"/>
          <property name="kie.keystore.key.ctrl.alias" value="kieserver"/>
          <property name="kie.keystore.key.ctrl.pwd" value="<SECRETKEYPASSWORD>"/>

  To configure the `kie-server` or `rest-all` user with KIE Server controller access, navigate to `~/$SERVER_HOME/standalone/configuration/standalone-full.xml`, uncomment the `org.kie.server` properties (if applicable), and add the controller user login credentials and controller location (if needed):

      <property name="org.kie.server.location" value="http://localhost:8080/kie-server/services/rest/server"/>
      <property name="org.kie.server.controller" value="http://localhost:8080/business-central/rest/controller"/>
      <property name="org.kie.server.controller.user" value="<USERNAME>"/>
      <property name="org.kie.server.id" value="default-kieserver"/>

  For more information about user roles and OptaPlanner installation options, see

Project dependencies

  The KIE Server controller Java client API requires the following dependencies on the relevant classpath of your Java project:

      <!-- For remote execution on controller -->
      <dependency>
        <groupId>org.kie.server</groupId>
        <artifactId>kie-server-controller-client</artifactId>
        <version>${optaplanner.version}</version>
      </dependency>

      <!-- For REST client -->
      <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>${resteasy.version}</version>
      </dependency>

      <!-- For WebSocket client -->
      <dependency>
        <groupId>io.undertow</groupId>
        <artifactId>undertow-websockets-jsr</artifactId>
        <version>${undertow.version}</version>
      </dependency>

      <!-- For debug logging (optional) -->
      <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
      </dependency>

  The `<version>` for OptaPlanner dependencies is the Maven artifact version for OptaPlanner currently used in your project (for example, 7.59.0.Final).

Client request configuration

  All Java client requests with the KIE Server controller Java client API must define at least the following controller communication components:

  - Credentials of the `rest-all` user if you installed Business Central, or the `kie-server` user if you installed the headless KIE Server controller separately from Business Central

  - KIE Server controller location for REST or WebSocket protocol:

    - Example REST URL: `http://localhost:8080/business-central/rest/controller`

    - Example WebSocket URL: `ws://localhost:8080/headless-controller/websocket/controller`

  - Marshalling format for API requests and responses (JSON or JAXB)

  - A `KieServerControllerClient` object, which serves as the entry point for starting the server communication using the Java client API

  - A `KieServerControllerClientFactory` defining REST or WebSocket protocol and user access

  - The KIE Server controller client service or services used, such as `listServerTemplates`, `getServerTemplate`, or `getServerInstances`

  The following are examples of REST and WebSocket client configurations with these components:

  Client configuration example with REST

      import org.kie.server.api.marshalling.MarshallingFormat;
      import org.kie.server.controller.api.model.spec.ServerTemplateList;
      import org.kie.server.controller.client.KieServerControllerClient;
      import org.kie.server.controller.client.KieServerControllerClientFactory;

      public class ListServerTemplatesExample {

          private static final String URL = "http://localhost:8080/business-central/rest/controller";
          private static final String USER = "baAdmin";
          private static final String PASSWORD = "password@1";

          private static final MarshallingFormat FORMAT = MarshallingFormat.JSON;

          public static void main(String[] args) {
              KieServerControllerClient client = KieServerControllerClientFactory.newRestClient(URL,
                                                                                                USER,
                                                                                                PASSWORD);

              final ServerTemplateList serverTemplateList = client.listServerTemplates();
              System.out.println(String.format("Found %s server template(s) at controller url: %s",
                                               serverTemplateList.getServerTemplates().length,
                                               URL));
          }
      }

  Client configuration example with WebSocket

      import org.kie.server.api.marshalling.MarshallingFormat;
      import org.kie.server.controller.api.model.spec.ServerTemplateList;
      import org.kie.server.controller.client.KieServerControllerClient;
      import org.kie.server.controller.client.KieServerControllerClientFactory;

      public class ListServerTemplatesExample {

          private static final String URL = "ws://localhost:8080/my-controller/websocket/controller";
          private static final String USER = "baAdmin";
          private static final String PASSWORD = "password@1";

          private static final MarshallingFormat FORMAT = MarshallingFormat.JSON;

          public static void main(String[] args) {
              KieServerControllerClient client = KieServerControllerClientFactory.newWebSocketClient(URL,
                                                                                                     USER,
                                                                                                     PASSWORD);

              final ServerTemplateList serverTemplateList = client.listServerTemplates();
              System.out.println(String.format("Found %s server template(s) at controller url: %s",
                                               serverTemplateList.getServerTemplates().length,
                                               URL));
          }
      }

#### 7.13.1. Sending requests with the KIE Server controller Java client API

The KIE Server controller Java client API enables you to connect to the KIE Server controller using REST or WebSocket protocols from your Java client application. You can use the KIE Server controller Java client API as an alternative to the KIE Server controller REST API to interact with your KIE Server templates (configurations), KIE Server instances (remote servers), and associated KIE containers (deployment units) in OptaPlanner without using the Business Central user interface.

Prerequisites

- KIE Server is installed and running.

- The KIE Server controller or headless KIE Server controller is installed and running.

- You have `rest-all` user role access to the KIE Server controller if you installed Business Central, or `kie-server` user role access to the headless KIE Server controller installed separately from Business Central.

- You have a Java project with OptaPlanner resources.

Procedure

1. In your client application, ensure that the following dependencies have been added to the relevant classpath of your Java project:

       <!-- For remote execution on controller -->
       <dependency>
         <groupId>org.kie.server</groupId>
         <artifactId>kie-server-controller-client</artifactId>
         <version>${optaplanner.version}</version>
       </dependency>

       <!-- For REST client -->
       <dependency>
         <groupId>org.jboss.resteasy</groupId>
         <artifactId>resteasy-client</artifactId>
         <version>${resteasy.version}</version>
       </dependency>

       <!-- For WebSocket client -->
       <dependency>
         <groupId>io.undertow</groupId>
         <artifactId>undertow-websockets-jsr</artifactId>
         <version>${undertow.version}</version>
       </dependency>

       <!-- For debug logging (optional) -->
       <dependency>
         <groupId>ch.qos.logback</groupId>
         <artifactId>logback-classic</artifactId>
         <version>${logback.version}</version>
       </dependency>

2. In the `~/kie/server/controller/client` folder of the Java client API in GitHub , identify the relevant Java client implementation for the request you want to send, such as the `RestKieServerControllerClient` implementation to access client services for KIE Server templates and KIE containers in REST protocol.

3. In your client application, create a `.java` class for the API request. The class must contain the necessary imports, the KIE Server controller location and user credentials, a `KieServerControllerClient` object, and the client method to execute, such as `createServerTemplate` and `createContainer` from the `RestKieServerControllerClient` implementation. Adjust any configuration details according to your use case.

   Creating and interacting with a KIE Server template and KIE containers

       import java.util.Arrays;
       import java.util.HashMap;
       import java.util.Map;

       import org.kie.server.api.marshalling.MarshallingFormat;
       import org.kie.server.api.model.KieContainerStatus;
       import org.kie.server.api.model.KieScannerStatus;
       import org.kie.server.api.model.ReleaseId;
       import org.kie.server.controller.api.model.spec.*;
       import org.kie.server.controller.client.KieServerControllerClient;
       import org.kie.server.controller.client.KieServerControllerClientFactory;

       public class RestTemplateContainerExample {

         private static final String URL = "http://localhost:8080/business-central/rest/controller";
         private static final String USER = "baAdmin";
         private static final String PASSWORD = "password@1";

           private static KieServerControllerClient client;

           public static void main(String[] args) {
               KieServerControllerClient client = KieServerControllerClientFactory.newRestClient(URL,
                                                                                                 USER,
                                                                                                 PASSWORD,
                                                                                                 MarshallingFormat.JSON);
               // Create server template and KIE container, start and stop KIE container, and delete server template
               ServerTemplate serverTemplate = createServerTemplate();
               ContainerSpec container = createContainer(serverTemplate);
               client.startContainer(container);
               client.stopContainer(container);
               client.deleteServerTemplate(serverTemplate.getId());
           }

           // Re-create and configure server template
           protected static ServerTemplate createServerTemplate() {
               ServerTemplate serverTemplate = new ServerTemplate();
               serverTemplate.setId("example-client-id");
               serverTemplate.setName("example-client-name");
               serverTemplate.setCapabilities(Arrays.asList(Capability.PROCESS.name(),
                                                            Capability.RULE.name(),
                                                            Capability.PLANNING.name()));

               client.saveServerTemplate(serverTemplate);

               return serverTemplate;
           }

           // Re-create and configure KIE containers
           protected static ContainerSpec createContainer(ServerTemplate serverTemplate){
               Map<Capability, ContainerConfig> containerConfigMap = new HashMap();

               ProcessConfig processConfig = new ProcessConfig("PER_PROCESS_INSTANCE", "kieBase", "kieSession", "MERGE_COLLECTION");
               containerConfigMap.put(Capability.PROCESS, processConfig);

               RuleConfig ruleConfig = new RuleConfig(500l, KieScannerStatus.SCANNING);
               containerConfigMap.put(Capability.RULE, ruleConfig);

               ReleaseId releaseId = new ReleaseId("org.kie.server.testing", "stateless-session-kjar", "1.0.0-SNAPSHOT");

               ContainerSpec containerSpec = new ContainerSpec("example-container-id", "example-client-name", serverTemplate, releaseId, KieContainerStatus.STOPPED, containerConfigMap);
               client.saveContainerSpec(serverTemplate.getId(), containerSpec);

               return containerSpec;
           }
       }

4. Run the configured `.java` class from your project directory to execute the request, and review the KIE Server controller response.

   If you enabled debug logging, KIE Server responds with a detailed response according to your configured marshalling format, such as JSON. If you encounter request errors, review the returned error code messages and adjust your Java configurations accordingly.

#### 7.13.2. Supported KIE Server controller Java clients

The following are some of the Java client services available in the `org.kie.server.controller.client` package of your OptaPlanner distribution. You can use these services to interact with related resources in the KIE Server controller similarly to the KIE Server controller REST API.

- `KieServerControllerClient`: Used as the entry point for communicating with the KIE Server controller

- `RestKieServerControllerClient`: Implementation used to interact with KIE Server templates and KIE containers in REST protocol (found in `~/org/kie/server/controller/client/rest`)

- `WebSocketKieServerControllerClient`: Implementation used to interact with KIE Server templates and KIE containers in WebSocket protocol (found in `~/org/kie/server/controller/client/websocket`)

For the full list of available KIE Server controller Java clients, see the Java client API source in GitHub.

#### 7.13.3. Example requests with the KIE Server controller Java client API

The following are examples of KIE Server controller Java client API requests for basic interactions with the KIE Server controller. For the full list of available KIE Server controller Java clients, see the Java client API source in GitHub.

Creating and interacting with KIE Server templates and KIE containers

  You can use the `ServerTemplate` and `ContainerSpec` services in the REST or WebSocket KIE Server controller clients to create, dispose, and update KIE Server templates and KIE containers, and to start and stop KIE containers, as illustrated in this example.

  Example request to create and interact with a KIE Server template and KIE containers

      import java.util.Arrays;
      import java.util.HashMap;
      import java.util.Map;

      import org.kie.server.api.marshalling.MarshallingFormat;
      import org.kie.server.api.model.KieContainerStatus;
      import org.kie.server.api.model.KieScannerStatus;
      import org.kie.server.api.model.ReleaseId;
      import org.kie.server.controller.api.model.spec.*;
      import org.kie.server.controller.client.KieServerControllerClient;
      import org.kie.server.controller.client.KieServerControllerClientFactory;

      public class RestTemplateContainerExample {

        private static final String URL = "http://localhost:8080/business-central/rest/controller";
        private static final String USER = "baAdmin";
        private static final String PASSWORD = "password@1";

          private static KieServerControllerClient client;

          public static void main(String[] args) {
              KieServerControllerClient client = KieServerControllerClientFactory.newRestClient(URL,
                                                                                                USER,
                                                                                                PASSWORD,
                                                                                                MarshallingFormat.JSON);
              // Create server template and KIE container, start and stop KIE container, and delete server template
              ServerTemplate serverTemplate = createServerTemplate();
              ContainerSpec container = createContainer(serverTemplate);
              client.startContainer(container);
              client.stopContainer(container);
              client.deleteServerTemplate(serverTemplate.getId());
          }

          // Re-create and configure server template
          protected static ServerTemplate createServerTemplate() {
              ServerTemplate serverTemplate = new ServerTemplate();
              serverTemplate.setId("example-client-id");
              serverTemplate.setName("example-client-name");
              serverTemplate.setCapabilities(Arrays.asList(Capability.PROCESS.name(),
                                                           Capability.RULE.name(),
                                                           Capability.PLANNING.name()));

              client.saveServerTemplate(serverTemplate);

              return serverTemplate;
          }

          // Re-create and configure KIE containers
          protected static ContainerSpec createContainer(ServerTemplate serverTemplate){
              Map<Capability, ContainerConfig> containerConfigMap = new HashMap();

              ProcessConfig processConfig = new ProcessConfig("PER_PROCESS_INSTANCE", "kieBase", "kieSession", "MERGE_COLLECTION");
              containerConfigMap.put(Capability.PROCESS, processConfig);

              RuleConfig ruleConfig = new RuleConfig(500l, KieScannerStatus.SCANNING);
              containerConfigMap.put(Capability.RULE, ruleConfig);

              ReleaseId releaseId = new ReleaseId("org.kie.server.testing", "stateless-session-kjar", "1.0.0-SNAPSHOT");

              ContainerSpec containerSpec = new ContainerSpec("example-container-id", "example-client-name", serverTemplate, releaseId, KieContainerStatus.STOPPED, containerConfigMap);
              client.saveContainerSpec(serverTemplate.getId(), containerSpec);

              return containerSpec;
          }
      }

Listing KIE Server templates and specifying connection timeout (REST)

  When you use REST protocol for KIE Server controller Java client API requests, you can provide your own `javax.ws.rs.core.Configuration` specification to modify the underlying REST client API, such as connection timeout.

  Example REST request to return server templates and specify connection timeout

      import java.util.concurrent.TimeUnit;
      import javax.ws.rs.core.Configuration;
      import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;

      import org.kie.server.api.marshalling.MarshallingFormat;
      import org.kie.server.controller.api.model.spec.ServerTemplateList;
      import org.kie.server.controller.client.KieServerControllerClient;
      import org.kie.server.controller.client.KieServerControllerClientFactory;

      public class RESTTimeoutExample {

        private static final String URL = "http://localhost:8080/business-central/rest/controller";
        private static final String USER = "baAdmin";
        private static final String PASSWORD = "password@1";

        public static void main(String[] args) {

            // Specify connection timeout
            final Configuration configuration =
                    new ResteasyClientBuilder()
                            .establishConnectionTimeout(10,
                                                          TimeUnit.SECONDS)
                            .socketTimeout(60,
                                             TimeUnit.SECONDS)
                              .getConfiguration();
              KieServerControllerClient client = KieServerControllerClientFactory.newRestClient(URL,
                                                                                                USER,
                                                                                                PASSWORD,
                                                                                                MarshallingFormat.JSON,
                                                                                                configuration);

              // Retrieve list of server templates
              final ServerTemplateList serverTemplateList = client.listServerTemplates();
              System.out.println(String.format("Found %s server template(s) at controller url: %s",
                                               serverTemplateList.getServerTemplates().length,
                                               URL));
          }
      }

Listing KIE Server templates and specifying event notifications (WebSocket)

  When you use WebSocket protocol for KIE Server controller Java client API requests, you can enable event notifications based on changes that happen in the particular KIE Server controller to which the client API is connected. For example, you can receive notifications when KIE Server templates or instances are connected to or updated in the KIE Server controller.

  Example WebSocket request to return server templates and specify event notifications

      import org.kie.server.api.marshalling.MarshallingFormat;
      import org.kie.server.controller.api.model.events.*;
      import org.kie.server.controller.api.model.spec.ServerTemplateList;
      import org.kie.server.controller.client.KieServerControllerClient;
      import org.kie.server.controller.client.KieServerControllerClientFactory;
      import org.kie.server.controller.client.event.EventHandler;

      public class WebSocketEventsExample {

          private static final String URL = "ws://localhost:8080/my-controller/websocket/controller";
          private static final String USER = "baAdmin";
          private static final String PASSWORD = "password@1";

          public static void main(String[] args) {
              KieServerControllerClient client = KieServerControllerClientFactory.newWebSocketClient(URL,
                                                                                                     USER,
                                                                                                     PASSWORD,
                                                                                                     MarshallingFormat.JSON,
                                                                                                     new TestEventHandler());

              // Retrieve list of server templates
              final ServerTemplateList serverTemplateList = client.listServerTemplates();
              System.out.println(String.format("Found %s server template(s) at controller url: %s",
                                               serverTemplateList.getServerTemplates().length,
                                               URL));
              try {
                  Thread.sleep(60 * 1000);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }

          // Set up event notifications
          static class TestEventHandler implements EventHandler {

              @Override
              public void onServerInstanceConnected(ServerInstanceConnected serverInstanceConnected) {
                  System.out.println("serverInstanceConnected = " + serverInstanceConnected);
              }

              @Override
              public void onServerInstanceDeleted(ServerInstanceDeleted serverInstanceDeleted) {
                  System.out.println("serverInstanceDeleted = " + serverInstanceDeleted);
              }

              @Override
              public void onServerInstanceDisconnected(ServerInstanceDisconnected serverInstanceDisconnected) {
                  System.out.println("serverInstanceDisconnected = " + serverInstanceDisconnected);
              }

              @Override
              public void onServerTemplateDeleted(ServerTemplateDeleted serverTemplateDeleted) {
                  System.out.println("serverTemplateDeleted = " + serverTemplateDeleted);
              }

              @Override
              public void onServerTemplateUpdated(ServerTemplateUpdated serverTemplateUpdated) {
                  System.out.println("serverTemplateUpdated = " + serverTemplateUpdated);
              }

              @Override
              public void onServerInstanceUpdated(ServerInstanceUpdated serverInstanceUpdated) {
                  System.out.println("serverInstanceUpdated = " + serverInstanceUpdated);
              }

              @Override
              public void onContainerSpecUpdated(ContainerSpecUpdated containerSpecUpdated) {
                  System.out.println("onContainerSpecUpdated = " + containerSpecUpdated);
              }
          }
      }

### 7.14. Securing password using key store

KIE server is using for some communication (e.g. REST api) basic authentication with passwords. From a security perspective it is not safe to store such passwords in clear text form on the disc. For this purpose a mechanism was developed to store passwords in a key store and then use it in the application.

#### 7.14.1. Simple use case

User wants to secure his password for communicating via REST client. He creates new keystore where he will put his password, he will setup system variables with the info to the keystore and KIE will automatically load the keystore and will use the password for securing the communication.

#### 7.14.2. Implementation and business logic

Current implementation is using key store if it is defined. If not, the functionality is falling back to old behavior using config parameters.

#### 7.14.3. System requirements

To use a key store we need to create it first. As JKS is not supporting symmetric keys we have to create JCEKS key store. Moreover, password can be stored in a key store only for Java 8 and above. For generating a key store you can use standard tool KeyTool which is part of JDK installation.

#### 7.14.4. Initialization of a key store

For keystore initialization we recommend to use keytool. Syntax is the following:

    ${JAVA_HOME}/bin/keytool -importpassword -keystore _keystore_url_ -keypass _alias_key_password_ -alias _password_alias_ -storepass _keystore_password_ -storetype JCEKS

- alias - alias name of the entry to process

- keypass - key password

- keystore - keystore name

- storepass - keystore password

- storetype - keystore type

After running this command user will be asked to enter the password which he wants to store.

#### 7.14.5. System parameters for loading key store

- kie.keystore.keyStoreURL - URL to a keystore which should be used

- kie.keystore.keyStorePwd - password to a keystore

- kie.keystore.key.server.alias - alias of the key for REST services where password is stored

- kie.keystore.key.server.pwd - password of an alias for REST services with stored password

- kie.keystore.key.ctrl.alias - alias of the key for default REST KIE Server controller where password is stored

- kie.keystore.key.ctrl.pwd - password of an alias for default REST KIE Server controller with stored password

#### 7.14.6. Example

1. create user and password in application server (it has to have kie-server role)

    $ ./bin/jboss-cli.sh --commands="embed-server --std-out=echo,/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity(identity=kieserver),/subsystem=elytron/filesystem-realm=ApplicationRealm:set-password(identity=kieserver, clear={password='kiePassword1!'}),/subsystem=elytron/filesystem-realm=ApplicationRealm:add-identity-attribute(identity=kieserver, name=role, value=['kie-server'])"

2. use key tool to create keystore with password in it

    ${JAVA_HOME}/bin/keytool -importpassword -keystore /home/kie/keystores/droolsServer.jceks -keypass keypwd -alias droolsKey -storepass serverpwd -storetype JCEKS

    Enter the password to be stored:
    Re-enter password:

    ${JAVA_HOME}/bin/keytool -importpassword -keystore /home/kie/keystores/droolsServer.jceks -keypass keypwd -alias restKey -storepass serverpwd -storetype JCEKS

    Enter the password to be stored:
    Re-enter password:

3. set following system properties on application server that will let the KIE Server or KIE Server controller to read password from keystore

        <system-properties>
            <property name="kie.keystore.keyStoreURL" value="file:///home/kie/keystores/droolsServer.jceks"/>
            <property name="kie.keystore.keyStorePwd" value="serverpwd"/>
            <property name="kie.keystore.key.server.alias" value="restKey"/>
            <property name="kie.keystore.key.server.pwd" value="keypwd"/>
            <property name="kie.keystore.key.ctrl.alias" value="droolsKey"/>
            <property name="kie.keystore.key.ctrl.pwd" value="keypwd"/>
        </system-properties>

4. start server to verify configuration

### 7.15. Prometheus metrics monitoring in OptaPlanner

Prometheus is an open-source systems monitoring toolkit that you can use with OptaPlanner to collect and store metrics related to the execution of business rules, processes, Decision Model and Notation (DMN) models, and other OptaPlanner assets. You can access the stored metrics through a REST API call to the KIE Server, through the Prometheus expression browser, or using a data-graphing tool such as Grafana.

You can configure Prometheus metrics monitoring for an on-premise KIE Server instance, for KIE Server on Spring Boot, or for a KIE Server deployment on Red Hat OpenShift Container Platform.

For the list of available metrics that KIE Server exposes with Prometheus, see the KIE Server Prometheus Extension page in GitHub.

#### 7.15.1. Configuring Prometheus metrics monitoring for KIE Server

You can configure your KIE Server instances to use Prometheus to collect and store metrics related to your business asset activity in OptaPlanner. For the list of available metrics that KIE Server exposes with Prometheus, see the KIE Server Prometheus Extension page in GitHub.

Prerequisites

- KIE Server is installed.

- You have `kie-server` user role access to KIE Server.

- Prometheus is installed. For information about downloading and using Prometheus, see the Prometheus documentation page.

Procedure

1. In your KIE Server instance, set the `org.kie.prometheus.server.ext.disabled` system property to `false` to enable the Prometheus extension. You can define this property when you start KIE Server or in the `standalone.xml` or `standalone-full.xml` file of OptaPlanner distribution.

2. If you are running OptaPlanner on Spring Boot, configure the required key in the `application.properties` system property:

   Spring Boot application.properties key for OptaPlanner and Prometheus

       kieserver.drools.enabled=true
       kieserver.dmn.enabled=true
       kieserver.prometheus.enabled=true

3. In the `prometheus.yaml` file of your Prometheus distribution, add the following settings in the `scrape_configs` section to configure Prometheus to scrape metrics from KIE Server:

   Scrape configurations in prometheus.yaml file

       scrape_configs:
         - job_name: 'kie-server'
           metrics_path: /SERVER_PATH/services/rest/metrics
           basicAuth:
             username: USER_NAME
             password: PASSWORD
           static_configs:
             - targets: ["HOST:PORT"]

   Scrape configurations in prometheus.yaml file for Spring Boot (if applicable)

       scrape_configs:
         - job_name: 'kie'
           metrics_path: /rest/metrics
           static_configs:
             - targets: ["HOST:PORT"]

   Replace the values according to your KIE Server location and settings.

4. Start the KIE Server instance.

   After you start the configured KIE Server instance, Prometheus begins collecting metrics and KIE Server publishes the metrics to the REST API endpoint `http://HOST:PORT/SERVER/services/rest/metrics` (or on Spring Boot, to `http://HOST:PORT/rest/metrics`).

5. In a REST client or curl utility, send a REST API request with the following components to verify that KIE Server is publishing the metrics:

   For REST client:

   - Authentication: Enter the user name and password of the KIE Server user with the `kie-server` role.

   - HTTP Headers: Set the following header:

     - `Accept`: `application/json`

   - HTTP method: Set to `GET`.

   - URL: Enter the KIE Server REST API base URL and metrics endpoint, such as `http://localhost:8080/kie-server/services/rest/metrics` (or on Spring Boot, `http://localhost:8080/rest/metrics`).

   For curl utility:

   - `-u`: Enter the user name and password of the KIE Server user with the `kie-server` role.

   - `-H`: Set the following header:

     - `accept`: `application/json`

   - `-X`: Set to `GET`.

   - URL: Enter the KIE Server REST API base URL and metrics endpoint, such as `http://localhost:8080/kie-server/services/rest/metrics` (or on Spring Boot, `http://localhost:8080/rest/metrics`).

   Example curl command for OptaPlanner on Red Hat JBoss EAP

       curl -u 'baAdmin:password@1' -X GET "http://localhost:8080/kie-server/services/rest/metrics"

   Example curl command for OptaPlanner on Spring Boot

       curl -u 'baAdmin:password@1' -X GET "http://localhost:8080/rest/metrics"

   Example server response

       # HELP kie_server_container_started_total Kie Server Started Containers
       # TYPE kie_server_container_started_total counter
       kie_server_container_started_total{container_id="task-assignment-kjar-1.0",} 1.0
       # HELP solvers_running Number of solvers currently running
       # TYPE solvers_running gauge
       solvers_running 0.0
       # HELP dmn_evaluate_decision_nanosecond DMN Evaluation Time
       # TYPE dmn_evaluate_decision_nanosecond histogram
       # HELP solver_duration_seconds Time in seconds it took solver to solve the constraint problem
       # TYPE solver_duration_seconds summary
       solver_duration_seconds_count{solver_id="100tasks-5employees.xml",} 1.0
       solver_duration_seconds_sum{solver_id="100tasks-5employees.xml",} 179.828255925
       solver_duration_seconds_count{solver_id="24tasks-8employees.xml",} 1.0
       solver_duration_seconds_sum{solver_id="24tasks-8employees.xml",} 179.995759653
       # HELP drl_match_fired_nanosecond Drools Firing Time
       # TYPE drl_match_fired_nanosecond histogram
       # HELP dmn_evaluate_failed_count DMN Evaluation Failed
       # TYPE dmn_evaluate_failed_count counter
       # HELP kie_server_start_time Kie Server Start Time
       # TYPE kie_server_start_time gauge
       kie_server_start_time{name="myapp-kieserver",server_id="myapp-kieserver",location="http://myapp-kieserver-demo-monitoring.127.0.0.1.nip.io:80/services/rest/server",version="7.4.0.redhat-20190428",} 1.557221271502E12
       # HELP kie_server_container_running_total Kie Server Running Containers
       # TYPE kie_server_container_running_total gauge
       kie_server_container_running_total{container_id="task-assignment-kjar-1.0",} 1.0
       # HELP solver_score_calculation_speed Number of moves per second for a particular solver solving the constraint problem
       # TYPE solver_score_calculation_speed summary
       solver_score_calculation_speed_count{solver_id="100tasks-5employees.xml",} 1.0
       solver_score_calculation_speed_sum{solver_id="100tasks-5employees.xml",} 6997.0
       solver_score_calculation_speed_count{solver_id="24tasks-8employees.xml",} 1.0
       solver_score_calculation_speed_sum{solver_id="24tasks-8employees.xml",} 19772.0

   If the metrics are not available in KIE Server, review and verify the KIE Server and Prometheus configurations described in this section.

   You can also interact with your collected metrics in the Prometheus expression browser at `http://HOST:PORT/graph`, or integrate your Prometheus data source with a data-graphing tool such as Grafana:

   Figure 108. Prometheus expression browser with KIE Server metrics
   Figure 109. Prometheus expression browser with KIE Server target
   Figure 110. Grafana dashboard with KIE Server metrics for DMN models
   Figure 111. Grafana dashboard with KIE Server metrics for solvers

Additional resources

- Getting Started with Prometheus

- Grafana Support for Prometheus

- Using Prometheus in Grafana

#### 7.15.2. Extending Prometheus metrics monitoring in KIE Server with custom metrics

After you configure your KIE Server instance to use Prometheus metrics monitoring, you can extend the Prometheus functionality in KIE Server to use custom metrics according to your business needs. Prometheus then collects and stores your custom metrics along with the default metrics that KIE Server exposes with Prometheus.

As an example, this procedure defines custom Decision Model and Notation (DMN) metrics to be collected and stored by Prometheus.

Prerequisites

- Prometheus metrics monitoring is configured for your KIE Server instance. For information about Prometheus configuration with KIE Server on-premise, see Configuring Prometheus metrics monitoring for KIE Server.

Procedure

1. Create an empty Maven project and define the following packaging type and dependencies in the `pom.xml` file for the project:

   Example pom.xml file in the sample project

       <packaging>jar</packaging>

       <properties>
         <version.org.kie>7.59.0.Final</version.org.kie>
       </properties>

       <dependencies>
         <dependency>
           <groupId>org.kie</groupId>
           <artifactId>kie-api</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-api</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-services-common</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-services-drools</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie.server</groupId>
           <artifactId>kie-server-services-prometheus</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie</groupId>
           <artifactId>kie-dmn-api</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.kie</groupId>
           <artifactId>kie-dmn-core</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.jbpm</groupId>
           <artifactId>jbpm-services-api</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.jbpm</groupId>
           <artifactId>jbpm-executor</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>org.optaplanner</groupId>
           <artifactId>optaplanner-core</artifactId>
           <version>${version.org.kie}</version>
         </dependency>
         <dependency>
           <groupId>io.prometheus</groupId>
           <artifactId>simpleclient</artifactId>
           <version>0.5.0</version>
         </dependency>
       </dependencies>

2. Implement the relevant listener from the `org.kie.server.services.prometheus.PrometheusMetricsProvider` interface as part of the custom listener class that defines your custom Prometheus metrics, as shown in the following example:

   Sample implementation of the `DMNRuntimeEventListener` listener in a custom listener class

       package org.kie.server.ext.prometheus;

       import io.prometheus.client.Gauge;
       import org.kie.dmn.api.core.ast.DecisionNode;
       import org.kie.dmn.api.core.event.AfterEvaluateBKMEvent;
       import org.kie.dmn.api.core.event.AfterEvaluateContextEntryEvent;
       import org.kie.dmn.api.core.event.AfterEvaluateDecisionEvent;
       import org.kie.dmn.api.core.event.AfterEvaluateDecisionServiceEvent;
       import org.kie.dmn.api.core.event.AfterEvaluateDecisionTableEvent;
       import org.kie.dmn.api.core.event.BeforeEvaluateBKMEvent;
       import org.kie.dmn.api.core.event.BeforeEvaluateContextEntryEvent;
       import org.kie.dmn.api.core.event.BeforeEvaluateDecisionEvent;
       import org.kie.dmn.api.core.event.BeforeEvaluateDecisionServiceEvent;
       import org.kie.dmn.api.core.event.BeforeEvaluateDecisionTableEvent;
       import org.kie.dmn.api.core.event.DMNRuntimeEventListener;
       import org.kie.server.api.model.ReleaseId;
       import org.kie.server.services.api.KieContainerInstance;

       public class ExampleCustomPrometheusMetricListener implements DMNRuntimeEventListener {

           private final KieContainerInstance kieContainer;

           private final Gauge randomGauge = Gauge.build()
                   .name("random_gauge_nanosecond")
                   .help("Random gauge as an example of custom KIE Prometheus metric")
                   .labelNames("container_id", "group_id", "artifact_id", "version", "decision_namespace", "decision_name")
                   .register();

           public ExampleCustomPrometheusMetricListener(KieContainerInstance containerInstance) {
               kieContainer = containerInstance;
           }

           public void beforeEvaluateDecision(BeforeEvaluateDecisionEvent e) {
           }

           public void afterEvaluateDecision(AfterEvaluateDecisionEvent e) {
               DecisionNode decisionNode = e.getDecision();
               ReleaseId releaseId = kieContainer.getResource().getReleaseId();
               randomGauge.labels(kieContainer.getContainerId(), releaseId.getGroupId(),
                                  releaseId.getArtifactId(), releaseId.getVersion(),
                                  decisionNode.getModelName(), decisionNode.getModelNamespace())
                       .set((int) (Math.random() * 100));
           }

           public void beforeEvaluateBKM(BeforeEvaluateBKMEvent event) {
           }

           public void afterEvaluateBKM(AfterEvaluateBKMEvent event) {
           }

           public void beforeEvaluateContextEntry(BeforeEvaluateContextEntryEvent event) {
           }

           public void afterEvaluateContextEntry(AfterEvaluateContextEntryEvent event) {
           }

           public void beforeEvaluateDecisionTable(BeforeEvaluateDecisionTableEvent event) {
           }

           public void afterEvaluateDecisionTable(AfterEvaluateDecisionTableEvent event) {
           }

           public void beforeEvaluateDecisionService(BeforeEvaluateDecisionServiceEvent event) {
           }

           public void afterEvaluateDecisionService(AfterEvaluateDecisionServiceEvent event) {
           }
       }

   The `PrometheusMetricsProvider` interface contains the required listeners for collecting Prometheus metrics. The interface is incorporated by the `kie-server-services-prometheus` dependency that you declared in your project `pom.xml` file.

   In this example, the `ExampleCustomPrometheusMetricListener` class implements the `DMNRuntimeEventListener` listener (from the `PrometheusMetricsProvider` interface) and defines the custom DMN metrics to be collected and stored by Prometheus.

3. Implement the `PrometheusMetricsProvider` interface as part of a custom metrics provider class that associates your custom listener with the `PrometheusMetricsProvider` interface, as shown in the following example:

   Sample implementation of the `PrometheusMetricsProvider` interface in a custom metrics provider class

       package org.kie.server.ext.prometheus;

       import org.jbpm.executor.AsynchronousJobListener;
       import org.jbpm.services.api.DeploymentEventListener;
       import org.kie.api.event.rule.AgendaEventListener;
       import org.kie.api.event.rule.DefaultAgendaEventListener;
       import org.kie.dmn.api.core.event.DMNRuntimeEventListener;
       import org.kie.server.services.api.KieContainerInstance;
       import org.kie.server.services.prometheus.PrometheusMetricsProvider;
       import org.optaplanner.core.impl.phase.event.PhaseLifecycleListener;
       import org.optaplanner.core.impl.phase.event.PhaseLifecycleListenerAdapter;

       public class MyPrometheusMetricsProvider implements PrometheusMetricsProvider {

           public DMNRuntimeEventListener createDMNRuntimeEventListener(KieContainerInstance kContainer) {
               return new ExampleCustomPrometheusMetricListener(kContainer);
           }

           public AgendaEventListener createAgendaEventListener(String kieSessionId, KieContainerInstance kContainer) {
               return new DefaultAgendaEventListener();
           }

           public PhaseLifecycleListener createPhaseLifecycleListener(String solverId) {
               return new PhaseLifecycleListenerAdapter() {
               };
           }

           public AsynchronousJobListener createAsynchronousJobListener() {
               return null;
           }

           public DeploymentEventListener createDeploymentEventListener() {
               return null;
           }
       }

   In this example, the `MyPrometheusMetricsProvider` class implements the `PrometheusMetricsProvider` interface and includes your custom `ExampleCustomPrometheusMetricListener` listener class.

4. To make the new metrics provider discoverable for KIE Server, create a `META-INF/services/org.kie.server.services.prometheus.PrometheusMetricsProvider` file in your Maven project and add the fully qualified class name of the `PrometheusMetricsProvider` implementation class within the file. For this example, the file contains the single line `org.kie.server.ext.prometheus.MyPrometheusMetricsProvider`.

5. Build your project and copy the resulting JAR file into the `~/kie-server.war/WEB-INF/lib` directory of your project.

6. Start the KIE Server and deploy the built project to the running KIE Server. You can deploy the project using the Business Central interface or the KIE Server REST API (a `PUT` request to `http://SERVER:PORT/kie-server/services/rest/server/containers/{containerId}`).

   After your project is deployed on a running KIE Server, Prometheus begins collecting metrics and KIE Server publishes the metrics to the REST API endpoint `http://HOST:PORT/SERVER/services/rest/metrics` (or on Spring Boot, to `http://HOST:PORT/rest/metrics`).

### 7.16. Performance tuning considerations with KIE Server

The following key concepts or suggested practices can help you optimize KIE Server performance. These concepts are summarized in this section as a convenience and are explained in more detail in the cross-referenced documentation, where applicable. This section will expand or change as needed with new releases of OptaPlanner.

Ensure that development mode is enabled during development

  You can set KIE Server or specific projects in Business Central to use `production` mode or `development` mode. By default, KIE Server and all new projects in Business Central are in development mode. This mode provides features that facilitate your development experience, such as flexible project deployment policies, and features that optimize KIE Server performance during development, such as disabled duplicate GAV detection. Use development mode until your OptaPlanner environment is established and completely ready for production mode.

  For more information about configuring the environment mode or duplicate GAV detection, see the following resources:

  - [_development_streamline_lifecycle]

  - Duplicate GAV detection

Adapt KIE Server capabilities and extensions to your specific needs

  The capabilities in KIE Server are determined by plug-in extensions that you can enable, disable, or further extend to meet your business needs. By default, KIE Server extensions are exposed through REST or JMS data transports and use predefined client APIs. You can extend existing KIE Server capabilities with additional REST endpoints, extend supported transport methods beyond REST or JMS, or extend functionality in the KIE Server client.

  This flexibility in KIE Server functionality enables you to adapt your KIE Server instances to your business needs, instead of adapting your business needs to the default KIE Server capabilities.

  For information about enabling, disabling, or extending KIE Server capabilities, see KIE Server capabilities and extensions.

### 7.17. KIE Server Task Assigning

#### 7.17.1. Introduction to business processes

Business process management systems (BPMS) products such as jBPM have the ability to model and execute multiple business processes. A business process is typically composed of nodes such as events, gateways, and tasks that are connected to each other for defining the process flow. Every type of node has a specific semantic and is instantiated by the process runtime engine when a process instance is executed. Business processes that require human interaction are modelled by using human task nodes.

The following image shows a process where three tasks require human interaction:

Figure 112. Example process

It is usual for a system that executes several process instances to have many human task instances that are waiting for an external human action.

Figure 113. Default task list

Red Hat build of OptaPlanner integrates with jBPM to provide the ability to assign human tasks to users as part of an optimized plan.

This is referred to as task assigning integration.

##### 7.17.1.1. BPM standard task assigning

In general, business process runtime engines assign human tasks to users on a group basis. The target audience is usually included as part of the human task configuration.

The following image shows how the Review Purchase Order human task is configured with the PurchaseDepartment group:

Figure 114. Human task configuration

At runtime, every time a new instance of the Review Purchase Order task is created it is automatically assigned to the PurchaseDepartment group with the status Ready. This makes the task automatically available to all users that belong to the group. All users in the group see it on their respective Task Inbox but none are the actual owner or responsible for the task. To be able to work with a particular task, a user must execute the claim operation to reserve the task for that user.

The following image shows an example of the claim operation execution for the task #152:

Figure 115. User claims a task

When the claim operation is executed, the task status is changed to Reserved and the task is assigned to the claiming user. In the preceding example, the claimer of the task is `wbadmin` user. After the user claims the task, he is known as the task "actual owner”.

Figure 116. Task claimed by wbadmin

Although this is the standard procedure for most BPMS products, it is not flexible enough for all use cases. For example, this procedure does not work well with scenarios where an optimal distribution of a huge set of tasks between users by given criteria is required. In these cases, users usually find a large list of tasks up-front but do not have the knowledge to claim and execute them in the best way.

##### 7.17.1.2. Red Hat build of OptaPlanner driven task assigning

Red Hat build of OptaPlanner and jBPM integration provides the ability to assign the human tasks produced by the process runtime engine between users according to an optimized plan. Instead of users having to claim the tasks, the tasks are assigned to them.

The following image shows how the tasks are assigned when integration is enabled.

Figure 117. Assignments produced by Red Hat build of OptaPlanner

The following assignments are shown:

- User katy is assigned to tasks #150 and #148

- User john is assigned to tasks #151 and #149

- Tasks #152, #153, #154, #155, #156 and #157 are left un-assigned (these tasks will be analysed later)

Behind the scenes the following actions took place:

1. All of the available tasks with the status "Ready" consumed by Red Hat build of OptaPlanner.

2. The users john and katy were identified as belonging to the "PurchaseDepartment" users group.

3. It was identified that the "Review Purchase Order" tasks were identified as defined for the "PurchaseDepartment" group.

4. An optimized plan was calculated and all of the tasks (including the "un-assigned" tasks) were assigned according to their configuration, for example group condition and Red Hat build of OptaPlanner optimization rules. The resulting plan stated that:

   - Tasks #150 and #148 must be assigned to katy

   - Tasks #151 and #149 must be assigned to john

5. Red Hat build of OptaPlanner executed the correct process runtime actions to make these assignments happen. Note that the users were not required to execute the "claim" operation. Instead they can focus on completing their respective assigned work and leave the distribution and assignment work to Red Hat build of OptaPlanner.

This simple example shows the main concept behind integration:

"Red Hat build of OptaPlanner analyses the available work, calculates an optimized plan, and produces the necessary assignments in the process runtime. Users then rely on that plan and focus on executing their assigned work".

Unassigned tasks

Usually, a running BPM creates many process instances and many human tasks. At the same time, users are working and completing these human tasks. This cycle is repeated over and over.

Red Hat build of OptaPlanner addresses this situation by re-calculating the optimized plan when new human tasks are created a/or completed and produce "new assignments" to reflect the new optimized plan. This is often achieved by combining different "Repeated Planning and Real Time Planning" techniques. For detailed information see the Red Hat build of OptaPlanner documentation.

Additionally it might be the case that a plan that was optimal at time N is no longer optimal at time N+1. For example, a higher priority task has arrived and must be performed as soon as possible. The direct impact of this situation is that the programmed assignments at time N might change at time N+1, which means that tasks are routinely re-assigned many times when the new optimized plans are calculated. One of Red Hat build of OptaPlanner’s strengths is the ability to react to a changing context.

User impact

If not controlled, continuous task re-assignment might negatively impact the user’s experience because they might feel that tasks come in and out of their workload randomly. This situation is present in other types of optimization problems as well and is usually managed by combining different repeated and continuous planning techniques. For detailed information see the "Repeated Planning" section of the Red Hat build of OptaPlanner documentation.

A simple strategy is to introduce the concept of a planning window which is a defined subset of the available work that will not be changed or re-assigned even when new plans are calculated. Only this subset is available to users. The tasks in the planning window are called published tasks.

The previous example contains a planning window with a size of two. This means that only two tasks from the optimized plan are assigned in the processes runtime for each user so that users have at most two tasks assigned to them and they must focus on those two tasks. As soon they start completing these tasks Red Hat build of OptaPlanner assigns them additional tasks according to the last optimized plan. However, internally Red Hat build of OptaPlanner maintains information about the best assignments for all of the tasks and not only the published tasks.

This is how the assignments are distributed in the preceding example:

- User katy is assigned to tasks #150 and #148 which belong to the planning window

- User john is assigned to tasks #151 and #149 which belong to the planning window

- The un-assigned tasks are outside of the planning window which means they are assigned only internally by Red Hat build of OptaPlanner. As long as these tasks remain unpublished they can be reassigned if necessary during the different optimized plans calculation.

#### 7.17.2. Configuring the integration

##### 7.17.2.1. Product version

The current task assigning integration implementation is provided for the Red Hat build of OptaPlanner, jBPM, and KIE Server 7.38.x+ series.

| KIE Server provides many installation alternatives, for example controller driven servers, standalone servers, high availability, etc. The purpose of this guide is to show you how to configure your KIE Server installation for the task assigning integration.

For KIE Server and jBPM configuration information see their respective product documentation.

The following procedure is recommended:

1. Install the KIE Servers topology that you require.

2. If you are using the jBPM schema generation scripts be sure to execute the following sql script corresponding to the target database management system:

   jBPM installer → /db/ddl-scripts/<dbms_vendor>/task_assigning_tables_<dbms_vendor>.sql

   For example, in the case of a db2 database you must execute the following script:

   jBPM installer → /db/ddl-scripts/db2/task_assigning_tables_db2.sql

   For more information related to these scripts see jBPM documentation.

   Note: the reverse script in cases where the generated schema needs to be deleted can be found in the same location and has the following name: task_assigning_tables_drop_<dbms_vendor>.sql

3. Be sure the process runtime is executing well.

4. Install a dedicated Planning kie-server (see next topics).

5. Complete the task assigning integration specific configuration parameters in all of the associated Process Runtime kie-servers and the Planning kie-server.

##### 7.17.2.2. Simplified architecture

The following simplified architecture identifies the key components and configuration parameters for the task assigning integration.

Figure 118. Simplified architecture

###### Process Runtime kie-server

This is the KIE Server instance where the business processes execute. In clustered and high-availability configurations, multiple instances can be used.

| The task assigning integration can manage multiple process runtime KIE Servers as long they share the same database where the process instances, human tasks instances, and so forth are stored and have the same set of deployed containers. In topologies where a KIE Server controller is configured this usually happens when they belong to the same KIE Server template. Be sure these statements are true before running the task assigning integration.

###### Planning kie-server

This is the KIE Server instance where OptaPlanner will execute, for example where the optimized plans and so forth, will be calculated and where the UserSystemService integration component will run. The task assigning integration requires a single dedicated KIE Server instance for this purpose. Be sure no other KIE Server extensions are enabled on this server.

##### 7.17.2.3. Configuration parameters setup

All of the configuration parameters that are defined in the next topics are defined through the Java system properties. In Wildfly and Red Hat Enterprise Application Server (EAP) installations, these parameters are usually configured in the <system-properties> section of the selected configuration file, for example:

    <server xmlns="urn:jboss:domain:8.0">
    ...
        <system-properties>
            ...
            <property name="org.kie.server.taskAssigning.runtime.ext.disabled" value="false"/>
            ...
        </system-properties>
    ...
    </server>

You can also use other methods of setting system properties, for example passing JVM parameters on the command line:

    -Dorg.kie.server.taskAssigning.runtime.ext.disabled=false

| It is recommended to use the same configuration method for all KIE Server required parameters.

##### 7.17.2.4. Process Runtime kie-server configuration

The following table shows the only parameter that must be configured in all of the Process Runtime kie-servers in the target topology.

Parameter | Requirement | Description
--- | --- | ---
org.kie.server.taskAssigning.runtime.ext.disabled | Not required | The default value is "true", meaning that the task assigning integration is always disabled. Must be set to "false" for making it work.

###### Process Runtime kie-server Wildfly/EAP configuration example

    <server>
    ...
        <system-properties>
           ...
            <property name="org.kie.server.taskAssigning.runtime.ext.disabled" value="false"/>
           ...
        </system-properties>
    ...
    </server>

##### 7.17.2.5. Planning kie-server configuration

The following topics explain the parameters that you must configure in the Planning kie-server. Whatever the target topology is, only one instance of this server will exist.

| The parameters tagged as "Required" must be set only in cases where the task assigning integration is enabled. Some of them have a default value that automatically applies when not set.

###### Global configuration parameters

Parameter | Requirement | Description
--- | --- | ---
org.kie.server.taskAssigning.planning.ext.disabled | Not required | The default value is "true", meaning that the task assigning integration is always disabled. Must be set to "false" for making it work.
org.kie.server.services.taskAssigning.core.model.planningUserId | Required | The default value is "planninguser". This value configures the user for being assigned with the tasks that no other user in the system can be assigned to. For example If a task has a required skill "astronaut" and no user can be found with this skill, it will be assigned to the planninguser. But it is not only restricted to skills, another example might be a task configured for a users group "Finance". If no user exists in that group it will be assigned to the planning user. It is strongly recommended that the planning user has the required human tasks administration grants in all of the target Process Runtime kie-servers. By doing so it can easily proceed to track and eventually re-assign the tasks that couldn’t be managed by the tasks assigning integration. Note: it is recommended to keep this name.
org.kie.server.taskAssigning.processRuntime.url | Required | The default value is http://localhost:8080/kie-server/services/rest/server This value configures the URL for connecting to the Process Runtime kie-server rest services. In a clustered environment a list of "|" separated urls can be used for doing load balancing between the different Process Runtime kie-servers.
org.kie.server.taskAssigning.processRuntime.user | Required | The default value is wbadmin This value configures the user id for connecting to the Process Runtime kie-server. In a clustered environment it must exist in all of the configured target servers. The configured user must belong to the human tasks administration group. This group is usually found by looking at the target Process Runtine kie-server configuration parameter: <property name="org.jbpm.ht.admin.group" value="process-admin"/> Following the example above the configured user must belong to the group "process-admin"
org.kie.server.taskAssigning.processRuntime.pwd | Required | No default value is set. This value configures the password for the user configured in org.kie.server.taskAssigning.processRuntime.user parameter.
org.kie.server.taskAssigning.processRuntime.targetUser | Required | No default value is set. This value configures the user ID used to execute the process runtime operations "on behalf of", and is usually the same as the value of the org.kie.server.taskAssigning.processRuntime.user parameter
org.kie.server.taskAssigning.processRuntime.key.alias | Not Required | No default value is set. This parameter can be used in cases where it is required to get the runtime user password from the KIE Server keystore and represents the alias for locating it.
org.kie.server.taskAssigning.processRuntime.key.pwd | Not Required | No default value is set. This parameter must be used in cases where the runtime user password is stored in the KIE Server keystore, and represents the password for accessing the corresponding keystore entry.
kie.keystore.keyStoreURL | Not Required | No default value is set. URL for the JCEKS that you want to use, for example file:///home/kie/keystores/keystore.jceks
kie.keystore.keyStorePwd | Not Required | No default value is set. Password for the JCEKS
org.kie.server.taskAssigning.processRuntime.timeout | Not Required | The default value is 90000. This value configures the timeout in milliseconds for the operation invocations on the Process runtime kie-server.
org.kie.server.taskAssigning.runtimeDelegate.pageSize | Not Required | The default value is 3000. This value configures the page size for the paged queries. The default value is good for most scenarios and it’s not recommended to be modified unless specific fine tunings are required.
org.kie.server.taskAssigning.solutionSyncInterval | Required | The default value is "PT2S" (two seconds). This value configures the time interval for the tasks information refreshing from the Process Runtime kie-server. The accepted format is based on the ISO-8601 duration format PnDTnHnMn.nS with days considered to be exactly 24 hours. For example: "PT1.500S": configures 1500 milliseconds. "PT0.500S": configures 500 milliseconds. "PT3S": configures 3000 milliseconds.
org.kie.server.taskAssigning.solutionSyncQueriesShift | Required | The default value is "PT10M" This value configures a timeshift for adjusting the tasks information refreshing queries. In most cases it should never be modified and should not be less than PT5M (five minutes). The accepted format is based on the ISO-8601 duration format PnDTnHnMn.nS with days considered to be exactly 24 hours.
org.kie.server.taskAssigning.publishWindowSize | Required | The default value is 2. This value configures the maximum amount of tasks per user that will be assigned to it in the Process Runtime kie-server when an optimized plan is calculated. See "published tasks" This value should usually be low 2, 3, or 4, since it is expected that the tasks will be assigned to the users according to an optimized plan that is changing over the time. High values might lead into the BPM Standard task assigning which could make the tasks assigning integration senseless.
org.kie.server.taskAssigning.usersSyncInterval | Required | The default value is "PT2H" (two hours) This value configures the time interval for the user’s information refreshing from the UserSystemService integration component. The accepted format is based on the ISO-8601 duration format PnDTnHnMn.nS with days considered to be exactly 24 hours.
org.kie.server.taskAssigning.waitForImprovedSolutionDuration | Not Required | The default value is "PT0S" (no wait) This value configures the time interval to improve a solution before the corresponding optimized plan is sent to the Process Runtime kie-server. Because this wait time is applied every time a new set of changes is processed it should usually be short, for example "PT0.500" (500 milliseconds). Use it in cases when early improvements are desired. The accepted format is based on the ISO-8601 duration format PnDTnHnMn.nS with days considered to be exactly 24 hours.
org.kie.server.taskAssigning.improveSolutionOnBackgroundDuration | Not Required | The default value is "PT1M" (one minute) This value configures the time interval for doing a background optimization of the current solution after the corresponding optimized plan is sent to the Process Runtime kie-server. In situations where no changes in the processes are produced and a better solution is calculated during that period, the new optimized plan is automatically sent to the Process Runtime kie-server. The accepted format is based on the ISO-8601 duration format PnDTnHnMn.nS with days considered to be exactly 24 hours.

###### Solver configuration parameters

As it was mentioned, the task assigning integration delegates the calculation of "which tasks must be assigned to whom" to Red Hat build of OptaPlanner and it will resolve this requirement by producing an optimized plan. This plan is calculated by using a Solver with a set of configured constraints. See Red Hat build of OptaPlanner product documentation for more information.

Two mechanisms are available for configuring the Red Hat build of OptaPlanner’s Solver specifics.

Note: The parameter tagged as "Required" must have a value independently of the selected Solver configuration mechanism.

###### Class path based solver configuration

This mechanism implements the ability of configuring the Solver by using a class path resource.

Parameter | Requirement | Description
--- | --- | ---
org.kie.server.taskAssigning.solver.configResource | Required | The default value is: "org/kie/server/services/taskassigning/solver/taskAssigningDefaultSolverConfig.xml" This value configures the path to a class-path resource with the Solver configuration. If the resource can’t be found or the configuration is wrong, a controlled error will be added to the Planning kie-server error messages and the task assigning integration won’t be initialized. The KIE Server APIs can be used for querying these error messages and checking the status.
org.kie.server.taskAssigning.solver.moveThreadCount | Not Required | The default value is AUTO. This value configures the solver’s ability of using multithreaded incremental solving. For more information see Red Hat build of OptaPlanner documentation. Note: when the container based solver configuration is used this value is not considered, the configuration provided in the KJAR is used instead.
org.kie.server.taskAssigning.solver.moveThreadBufferSize | Not Required | No default value is set. This value power tweaks the number of moves that are selected but won’t be foraged when multithreaded incremental solving is used. Setting it too low reduces performance, but setting it too high too. Unless you’re deeply familiar with the inner workings of multithreaded solving, don’t configure this parameter. For more information see Red Hat build of OptaPlanner documentation. Note: when the container based solver configuration is used this value is not considered, the configuration provided in the KJAR is used instead.
org.kie.server.taskAssigning.solver.threadFactoryClass | Not Required | No default value is set. The threadFactoryClass allows you to plug in a custom ThreadFactory for environments where arbitrary thread creation should be avoided. For more information see Red Hat build of OptaPlanner documentation. Note: when the container based solver configuration is used this value is not considered, the configuration provided in the KJAR is used instead.

| The default solver configuration includes a set of constraints for implementing optimized task assigning, therefore it is not necessary to provide a different set of constraints in most cases. Use cases that require specific tunings, for example related to business data, can use this alternative. However it is recommended to use a Container based configuration for these purposes.

###### Container based solver configuration

This mechanism implements the ability to configure the Solver by using a container. Finally, given that the KIE Server architecture is based on containers this is usually the recommended approach. However in many of the use cases the by default configuration is good enough and no container configuration is necessary see Default Constraints

The following table shows the container-based configuration parameters:

Parameter | Requirement | Description
--- | --- | ---
org.kie.server.taskAssigning.solver.container.id | Not Required | No default value is set. This value configures the Identifier of the container to use. When set the container based configuration will be activated and the following container related parameters are required.
org.kie.server.taskAssigning.solver.container.groupId | Required if the container configuration is activated | No default value is set. This value configures the Maven groupId of the artifact to use for creating the container when needed.
org.kie.server.taskAssigning.solver.container.artifactId | Required if the container configuration is activated | No default value is set. This value configures the Maven artifactId for the artifact to use for creating the container when needed.
org.kie.server.taskAssigning.solver.container.version | Required if the container configuration is activated | No default value is set. This value configures the Maven version for the artifact to use for creating the container when needed.
org.kie.server.taskAssigning.solver.configResource | Required if the container configuration is activated | This value configures the path to the resource with the Solver configuration in the container class-path.

In case of errors, analogous to the "Class path based solver configuration" proper KIE Server error messages will be generated and the task assigning integration won’t be initialized. The KIE Server APIs can be used for querying these error messages and checking the status.

###### UserSystemService integration component

Calculating an optimized plan for assigning tasks to users often requires considering business related information. Common examples, included in the current task assigning integration version, are the usage of the groups, the skills that a given user has or the affinities in certain topics, etc. See Skills and Affinities. This business oriented information must be provided by each particular installation and is delegated to the UserSystemService integration component. It is up to the tasks assigning integrator to provide this component.

UserSystemService API

A user system service component must implement the following API.

    public interface UserSystemService {

        /**
         * Invoked by the task assigning integration as part of the initialization procedure and
         * before any other method is invoked.
         */
        void start();

        /**
         * Invoked by the task assigning integration as part of the initialization procedure and
         * after the start() method is invoked.
         * @throws Exception if the test method failed.
         */
        void test() throws Exception;

        /**
         * @return the name of the UserSystemService implementation.
         */
        String getName();

        /**
         * @return the list of all users present in the external user system. This method is normally
         * invoked each time the solver is initialized or when the users information is updated from
         * the external user system.
         */
        List<User> findAllUsers();

        /**
         * Get the user information for a particular user.
         * @param id user identifier for querying.
         * @return the User corresponding to the given identifier, null if no user was found.
         */
        User findUser(String id);
    }

###### UserSystemService configuration

Analogous to the Solver configuration two mechanisms are available for configuring the UserSystemService and in both cases the standard Java SPI (Service Provider Interface) and ServiceLoader mechanisms are used for its instantiation.

###### Class path based UserSystemService configuration

Use the following resource for configuring the different UserSystemService provider implementations:

META-INF/services/org.kie.server.services.taskassigning.user.system.api.UserSystemService

And finally add the following configuration parameters for configuring the selected implementation:

Parameter | Requirement | Description
--- | --- | ---
org.kie.server.taskAssigning.userSystem.name | Required | No default value is set. This value configures the name of the UserSystemService provider instance to use. See: UserSystemService.getName() All of the configured providers are loaded from the application class-path and the one that matches with the configured name will be used. A simple user system service implementation is provided see SimpleUserSystemService

###### Container based UserSystemService configuration

Use the following resource in your Kie Module (KJAR) to configure the different UserSystemService provider implementations:

project_home/src/main/resources/META-INF/services/org.kie.server.services.taskassigning.user.system.api.UserSystemService

And finally add the following configuration parameters for configuring the selected implementation:

Parameter | Requirement | Description
--- | --- | ---
org.kie.server.taskAssigning.userSystem.name | Required | No default value is set. This value configures the name of the UserSystemService provider instance to use. See: UserSystemService.getName()
org.kie.server.taskAssigning.userSystem.container.id | Not Required | No default value is set. This value configures the Identifier of the container to use. When set the container based configuration will be activated and all of the potential UserSystemService providers that might be defined in the container class-path will be considered for selection, additionally to the ones in the application class-path. The following parameters will be required.
org.kie.server.taskAssigning.userSystem.container.groupId | Required if the container configuration is activated. | No default value is set. This value configures the Maven groupId of the artifact to use for creating the container when needed.
org.kie.server.taskAssigning.userSystem.container.artifactId | Required if the container configuration is activated. | No default value is set. This value configures the Maven artifactId for the artifact to use for creating the container when needed.
org.kie.server.taskAssigning.userSystem.container.version | Required if the container configuration is activated. | No default value is set. This value configures the Maven version for the artifact to use for creating the container when needed.

In case of errors, for example if the configured provider name was not found, the container couldn’t be instantiated, etc, a controlled error will be added to the Planning kie-server error messages and the task assigning integration won’t be initialized. The KIE Server APIs can be used for querying these error messages and checking the status.

###### SimpleUserSystemService

The SimpleUserSystemService is a basic UserSystemService implementation that loads the user definitions, skills and affinities from Java properties file in the format used by the Wildfly/EAP application servers. This implementation is always present in the Planning kie-server and is intended mainly for development and testing purposes.

The following example shows a user definitions file:

    katy=analyst,HR
    john=IT,Developer

In this example, two users are defined:

- User katy that belongs to the groups analyst and HR

- User john that belongs to the groups IT and Developer

The following parameters can be used to configure it:

Parameter | Requirement | Description
--- | --- | ---
org.kie.server.taskAssigning.userSystem.name | Required | Must be the value SimpleUserSystemService
org.kie.server.services.taskassigning.user.system.simple.users | Required | This value configures a Planning kie-server web application accessible path with the user definitions file. For example in Wildfly/EAP installations can be like this. ${jboss.server.config.dir}/roles.properties Note: the configured file must have the same values as the roles.properties files of the Process Runtime kie-servers in the target topology.
org.kie.server.services.taskassigning.user.system.simple.skills | Not Required | This value configures a Planning kie-server web application accessible path with the users skills definitions if desired, see Skills and Affinities. For example in Wildfly/EAP installations can be like this. ${jboss.server.config.dir}/skills.properties Note: the format is analogous to the user definitions file. katy=skill1,skill2 john=skill1,skill2
org.kie.server.services.taskassigning.user.system.simple.affinities | Not Required | This value configures a Planning kie-server web application accessible path with the users affinities definition if desired, Skills and Affinities. For example in Wildfly/EAP installations can be like this. ${jboss.server.config.dir}/affinities.properties Note: the format is analogous to the user definitions file. katy=affinity1,affinity4 In this example john has no affinities.

###### Planning kie-server Wildfly/EAP configuration example

Below is an extract of the task assigning configuration parameters for a Wildfly/EAP server.

    <server>
    ...
    <system-properties>
    ...
      <!-- the following kie-server extensions must be disabled in the Planning kie-server -->
      <property name="org.optaplanner.server.ext.disabled" value="true"/>
      <property name="org.jbpm.server.ext.disabled" value="true"/>
      <property name="org.jbpm.ui.server.ext.disabled" value="true"/>
      <property name="org.jbpm.case.server.ext.disabled" value="true"/>
      <property name="org.kie.dmn.server.ext.disabled" value="true"/>
      <property name="org.kie.swagger.server.ext.disabled" value="true"/>

      <!-- enable the TaskAssigningPlanningKieServerExtension -->
      <property name="org.kie.server.taskAssigning.planning.ext.disabled" value="false"/>

      <property name="org.kie.server.taskAssigning.processRuntime.url"
                value="http://localhost:8080/kie-server/services/rest/server"/>
      <property name="org.kie.server.taskAssigning.processRuntime.user" value="wbadmin"/>
      <property name="org.kie.server.taskAssigning.processRuntime.pwd" value="wbadmin"/>
      <property name="org.kie.server.taskAssigning.processRuntime.targetUser" value="wbadmin"/>
      <property name="org.kie.server.taskAssigning.solutionSyncInterval" value="PT2S"/>

      <!-- example of a Solver configuration based on a user provided kjar -->
      <!--
      <property name="org.kie.server.taskAssigning.solver.configResource" value="org/kie/server/services/taskassigning/solver/taskAssigningDefaultSolverConfig.xml"/>
      <property name="org.kie.server.taskAssigning.solver.container.id"
                value="kie-server-task-assigning-default-planner-kjar-container"/>
      <property name="org.kie.server.taskAssigning.solver.container.groupId" value="org.kie.server"/>
      <property name="org.kie.server.taskAssigning.solver.container.artifactId"
                value="kie-server-task-assigning-default-planner-kjar"/>
      <property name="org.kie.server.taskAssigning.solver.container.version" value="X.XX.XXX"/>
      -->

      <!-- default SimpleUserSystemService configuration -->
      <property name="org.kie.server.taskAssigning.userSystem.name" value="SimpleUserSystemService"/>
      <property name="org.kie.server.services.taskassigning.user.system.simple.users"
                value="${jboss.server.config.dir}/roles.properties"/>

      <!-- un-comment and configure if skills information will be loaded -->
      <!--
      <property name="org.kie.server.services.taskassigning.user.system.simple.skills"
                value="${jboss.server.config.dir}/skills.properties"/>
      -->

      <!-- un-comment and configure if affinities information will be loaded -->
      <!--
      <property name="org.kie.server.services.taskassigning.user.system.simple.affinities"
                value="${jboss.server.config.dir}/affinities.properties"/>
      -->
      <!-- end of default SimpleUserSystemService configuration -->

      <!-- example of a UserSystemService configuration based on a user provided kjar -->
      <!--
      <property name="org.kie.server.taskAssigning.userSystem.name"
                value="SimpleUserSystemServiceByKjar"/>
      <property name="org.kie.server.taskAssigning.userSystem.container.id"
                value="task-assigning-user-system-service-simple-by-kjar-container"/>
      <property name="org.kie.server.taskAssigning.userSystem.container.groupId"
                value="org.kie.server"/>
      <property name="org.kie.server.taskAssigning.userSystem.container.artifactId"
                value="kie-server-task-assigning-user-system-simple-kjar"/>
      <property name="org.kie.server.taskAssigning.userSystem.container.version" value="X.XX.XXX"/>
      -->
    ...
    </system-properties>
    ...
    </server>

###### Spring Boot configuration

When the KIE Server Spring Boot Starter version is used the following configuration parameters are used to configure the task assigning integration. These parameters are usually configured in the corresponding Spring Boot application.properties file. The same statements as for standard KIE Server topologies apply in this case.

Parameter | Requirement | Description
--- | --- | ---
kieserver.taskAssigning.runtime.enabled | Required | Must be set to "true" in order to enable the task assigning integration in the Process Runtime kie-server
kieserver.taskAssigning.planning.enabled | Required | Must be set to "true" in order to enable the task assigning integration in the Planning kie-server
taskassigning.core.model.planningUserId | Required | This value is analogous to the org.kie.server.services.taskAssigning.core.model.planningUserId configuration parameter, see Global configuration parameters
taskassigning.processRuntime.url | Required | This value is analogous to the org.kie.server.taskAssigning.processRuntime.url configuration parameter, see Global configuration parameters
taskassigning.processRuntime.user | Required | This value is analogous to the org.kie.server.taskAssigning.processRuntime.user configuration parameter, see Global configuration parameters
taskassigning.processRuntime.pwd | Required | This value is analogous to the org.kie.server.taskAssigning.processRuntime.pwd configuration parameter, see Global configuration parameters
taskassigning.processRuntime.targetUser | Required | This value is analogous to the org.kie.server.taskAssigning.processRuntime.targetUser configuration parameter, see Global configuration parameters
taskassigning.processRuntime.key.alias | Not Required | This value is analogous to the org.kie.server.taskAssigning.processRuntime.key.alias configuration parameter, see Global configuration parameters
taskassigning.processRuntime.key.pwd | Not Required | This value is analogous to the org.kie.server.taskAssigning.processRuntime.key.pwd configuration parameter, see Global configuration parameters
taskassigning.processRuntime.timeout | Not Required | This value is analogous to the org.kie.server.taskAssigning.processRuntime.timeout configuration parameter, see Global configuration parameters
taskassigning.runtimeDelegate.pageSize | Not Required | This value is analogous to the org.kie.server.taskAssigning.runtimeDelegate.pageSize configuration parameter, see Global configuration parameters
taskassigning.solutionSyncInterval | Required | This value is analogous to the org.kie.server.taskAssigning.solutionSyncInterval configuration parameter, see Global configuration parameters
taskassigning.solutionSyncQueriesShift | Required | This value is analogous to the org.kie.server.taskAssigning.solutionSyncQueriesShift configuration parameter, see Global configuration parameters
taskassigning.publishWindowSize | Required | This value is analogous to the org.kie.server.taskAssigning.publishWindowSize configuration parameter, see Global configuration parameters
taskassigning.usersSyncInterval | Required | This value is analogous to the org.kie.server.taskAssigning.usersSyncInterval configuration parameter, see Global configuration parameters
taskassigning.waitForImprovedSolutionDuration | Not Required | This value is analogous to the org.kie.server.taskAssigning.waitForImprovedSolutionDuration configuration parameter, see Global configuration parameters
taskassigning.improveSolutionOnBackgroundDuration | Not Required | This value is analogous to the org.kie.server.taskAssigning.improveSolutionOnBackgroundDuration configuration parameter, see Global configuration parameters
taskassigning.solver.configResource | Required | This value is analogous to the org.kie.server.taskAssigning.solver.configResource configuration parameter, see Solver configuration parameters
taskassigning.solver.moveThreadCount | Not Required | This value is analogous to the org.kie.server.taskAssigning.solver.moveThreadCount configuration parameter, see Solver configuration parameters
taskassigning.solver.moveThreadBufferSize | Not Required | This value is analogous to the org.kie.server.taskAssigning.solver.moveThreadBufferSize configuration parameter, see Solver configuration parameters
taskassigning.solver.threadFactoryClass | Not Required | This value is analogous to the org.kie.server.taskAssigning.solver.threadFactoryClass configuration parameter, see Solver configuration parameters
taskassigning.solver.container.id | Not Required | This value is analogous to the org.kie.server.taskAssigning.solver.container.id configuration parameter, see Container based solver configuration
taskassigning.solver.container.groupId | Required if the container configuration is activated | This value is analogous to the org.kie.server.taskAssigning.solver.container.groupId configuration parameter, see Container based solver configuration
taskassigning.solver.container.artifactId | Required if the container configuration is activated | This value is analogous to the org.kie.server.taskAssigning.solver.container.artifactId configuration parameter, see Container based solver configuration
taskassigning.solver.container.version | Required if the container configuration is activated | This value is analogous to the org.kie.server.taskAssigning.solver.container.version configuration parameter, see Container based solver configuration
taskassigning.solver.configResource | Required if the container configuration is activated | This value is analogous to the org.kie.server.taskAssigning.solver.configResource configuration parameter, see Container based solver configuration
taskassigning.userSystem.name | Required | This value is analogous to the org.kie.server.taskAssigning.userSystem.name configuration parameter, see UserSystemService configuration
taskassigning.userSystem.container.id | Not Required | This value is analogous to the org.kie.server.taskAssigning.userSystem.container.id configuration parameter, see Container based UserSystemService configuration
taskassigning.userSystem.container.groupId | Required if the container configuration is activated | This value is analogous to the org.kie.server.taskAssigning.userSystem.container.groupId configuration parameter, see Container based UserSystemService configuration
taskassigning.userSystem.container.artifactId | Required if the container configuration is activated | This value is analogous to the org.kie.server.taskAssigning.userSystem.container.artifactId configuration parameter, see Container based UserSystemService configuration
taskassigning.userSystem.container.version | Required if the container configuration is activated | This value is analogous to the org.kie.server.taskAssigning.userSystem.container.version configuration parameter, see Container based UserSystemService configuration
tastaskassigning.userSystem.simple.users | Required if the Simple User System is configured | This value is analogous to the org.kie.server.services.taskassigning.user.system.simple.users configuration parameter, see SimpleUserSystemService
taskassigning.userSystem.simple.skills | Not Required | This value is analogous to the org.kie.server.services.taskassigning.user.system.simple.skills configuration parameter, see SimpleUserSystemService
taskassigning.userSystem.simple.affinities | Not Required | This value is analogous to the org.kie.server.services.taskassigning.user.system.simple.affinities configuration parameter, see see SimpleUserSystemService

###### Default Constraints

The following table gives a high level description of the set of constraints that are included in the task assigning integration. These constraints are used for the construction of the optimized plan, in other words "for determining which tasks should be assigned to whom".

In general a large set of use cases can be covered by using them and no extensions are required, but it is possible to work with a user provided-customized set of constraints if needed, see Container based solver configuration.

Optimized solutions construction is made by using a BendableLongScore with two levels of Hard constraints and six levels of Soft constraints. These constraint levels can be customized by following a set of restrictions.

Constraint | Level/Requirement | Description
--- | --- | ---
Required Potential Owner | Hard Constraint 0 (required) | Determines that a task must be assigned to one of it is "Potential Owners", or to the "Planning User" in cases where no "Potential Owners" are found. User provided customizations must always include this constraint as the first level hard constraint. Otherwise the business process semantics won’t be considered by the task assigning integration, i.e., tasks might be assigned to users that are not "Potential Owners" for it. In cases where this constraint is still customized, it must always consider assigning the "Planning User" when no other user fits the customized condition.
Required Skills | Hard Constraint 1 | Determines that a task can only be assigned to a user that has all of the task’s configured skills, see Skills and Affinities. If a task has configured skills but no user with all of these skills can be found it’ll be assigned to the "Planning User". If the task doesn’t have configured skills the constraint has no effect. In cases where this constraint is customized, it must always consider assigning the "Planning User" when no other user fits the customized condition.
PlanningUser assignment | Soft Constraint 0 (required) | Penalizes the "Planning User" assignment. This constraint enforces the minimization of the "Planning User" assignment and ensures it’ll be assigned as the "last available option" Do not customize or change this constraint.
High level priority | Soft Constraint 1 | Enforces the assignment of higher priority tasks first whenever it is possible.
Desired Affinities | Soft Constraint 2 | Makes a best effort for assigning tasks according to its configured affinities, see Skills and Affinities If a task has configured affinities, whenever it is possible, a user with the most of them will be picked for its assignment. If the task doesn’t have configured affinities the constraint has no effect.
Minimize makespan | Soft Constraint 3 (required) | Reduce the time to complete all tasks. This constraint must always be included.
Medium level priority | Soft Constraint 4 | Medium level priority tasks are assigned after higher priority tasks whenever it is possible.
Low level priority | Soft Constraint 5 | Low level priority tasks are assigned lastly whenever it is possible.

| The current TaskAssigningSolution implementation is based on a BendableLongScore scoring function and thus any potential extension of the provided constraints, etc., typically by using a user provided KJAR, will be based on it. However this scoring function as well as the core model classes might change in future releases.

###### Constraints configuration by using a DRL file

The following example shows the key parts of the DRL file that contains the constraints configurations.

    // ############################################################################
    // Hard constraints
    // ############################################################################

    // A task can only be assigned to one of its potential owners or to the PlanningUser
    rule "Required Potential Owner"
       when
           $task : Task(user != null, !TaskAssigningConditions.userMeetsPotentialOwnerOrPlanningUserCondition($task, user))
       then
           scoreHolder.addHardConstraintMatch(kcontext, 0, -1);
    end

    // A task with defined skills can only be assigned to users that has all of the of them or to the PlanningUser
    rule "Required Skills"
       when
           $task : Task(user != null, !TaskAssigningConditions.userMeetsRequiredSkillsOrPlanningUserCondition($task, user))
       then
           scoreHolder.addHardConstraintMatch(kcontext, 1, -1);
    end

    // ############################################################################
    // Soft constraints
    // ############################################################################

    // First level soft constraint for penalizing the assignment of the PLANNING_USER.
    rule "PlanningUser assignment"
       when
           Task(user != null, ModelConstants.IS_PLANNING_USER.test(user.getEntityId()))
       then
           // a penalization is added each time the PLANNING_USER is assigned.
           scoreHolder.addSoftConstraintMatch(kcontext, 0, -1);
    end

    // Second level soft constraint for penalizing the assignment of the PLANNING_USER.
    rule "High level priority"
       when
           $task : Task(user != null, PriorityHelper.isHighLevel(priority))
       then
           scoreHolder.addSoftConstraintMatch(kcontext, 1, PriorityHelper.calculateWeightedPenalty($task.getPriority(), $task.getEndTimeInMinutes()));
    end

    // Third level soft constraint, when a task has defined affinities consider assigning users that match
    // the most of them as possible.
    rule "Desired Affinities"
       when
           $task : Task(user != null, user.isEnabled())
       then
           scoreHolder.addSoftConstraintMatch(kcontext, 2, TaskHelper.countMatchingLabels($task, $task.getUser(), DefaultLabels.AFFINITIES.name()));
    end

    // Fourth level soft constraint.
    rule "Minimize makespan (starting with the latest ending user first)"
       when
           Task(user != null, nextTask == null, $endTimeInMinutes : endTimeInMinutes)
       then
           scoreHolder.addSoftConstraintMatch(kcontext, 3, - ($endTimeInMinutes * $endTimeInMinutes));
    end

    // Fifth level soft constraint.
    rule "Medium level priority"
       when
           $task : Task(user != null, PriorityHelper.isMediumLevel(priority))
       then
           scoreHolder.addSoftConstraintMatch(kcontext, 4, PriorityHelper.calculateWeightedPenalty($task.getPriority(), $task.getEndTimeInMinutes()));
    end

    // Sixth level soft constraint.
    rule "Low level priority"
       when
           $task : Task(user != null, PriorityHelper.isLowLevel(priority))
       then
           scoreHolder.addSoftConstraintMatch(kcontext, 5, PriorityHelper.calculateWeightedPenalty($task.getPriority(), $task.getEndTimeInMinutes()));
    end

| The current by default DRL might change in future versions and thus can not be considered as part of the product public API. Any potential customization of the provided constraints might use this DRL as a start point or could also use other mechanisms as the constraints streams for implementing them.

###### Skills and Affinities

The use of skills and affinities implements the ability of declaring business related data for being considered by the default provided constraints or any other user defined ones. This is a fine grained decision mechanism that you can use on top of the groups-based assignment semantics defined in the business process.

Internally, this mechanism is based on the ability to label the human tasks generated by the business processes runtime and the users information.

Labeling mechanism

The following procedure shows how the labeling mechanism converts information in human tasks, and users information to labels:

Figure 119. Tasks Labeling

1. Any human task is created in the processes runtime.

2. When the new task is detected by the task assigning solution refreshing mechanism, a set of LabelValueExtrators is applied.

3. These LabelValueExtractors can transform any piece of information in the human task or user into a label.

4. The default constraints consider these labels.

In the preceding example,the following labels are produced:

- The input data "skills", with the value "skill1, skill2" resulted in the label SKILLS with the following set of values {"skill1", "skill2"}

- The input data "affinities" with the value "affinity1" resulted in the label AFFINITIES with the following set of values {"affinity1"}

| Task labels are calculated only the first time the task is identified by the task assigning integration and can use any of the information present in the task.

User labeling works in a similar way:

Figure 120. Tasks Labeling

###### Default HumanTask and User LabelValueExtractors

Four label value extractors are provided to manage the SKILLS and AFFINITIES labels.

Extractor Name | Description
--- | ---
DefaultTaskDataSkillsValueExtractor | Processes the human task "skills" input value as a string of comma separated values, and creates a java Set<Object> with tokenized String values. The resulting set is assigned to the label SKILLS. For example, the "skills" input value "english,finance" is extracted as a set with the values {"english", "finance"} and assigned to the label with name SKILLS. By default extraction can be customized by using the following system property for defining the task input value from where the SKILLS will be extracted. For example: org.kie.server.services.taskassigning.planning.data.DefaultTaskDataSkillsValueExtractor.skills=someOtherName
DefaultTaskDataAffinitiesValueExtractor | Processes the human task "affinities" input value, as a string comma separated values, and creates a java Set<Object> with tokenized String values. The resulting set is assigned to the label AFFINITIES. Ej. The "affinities" input value "news,history" is extracted as a set with the values {"news", "history"} and assigned to the label with name AFFINITIES. By default extraction can be customized by using the following system property for defining the task input value from where the AFFINITIES will be extracted. For example: org.kie.server.services.taskassigning.planning.data.DefaultTaskDataAffinitiesValueExtractor.affinities=someOtherName
DefaultUserSkillsValueExtractor | Analogous to the DefaultTaskDataSkillsValueExtractor By default extraction can be customized by using the following system property for defining the user attribute from where the SKILLS will be extracted. For example: org.kie.server.services.taskassigning.planning.data.DefaultUserSkillsValueExtractor.skills=someOtherName
DefaultUserAffinitiesValueExtractor | Analogous to the DefaultTaskDataAffinitiesValueExtractor By default extraction can be customized by using the following system property for defining the user attribute from where the AFFINITIES will be extracted. For example: org.kie.server.services.taskassigning.planning.data.DefaultUserAffinitiesValueExtractor.affinities=someOtherName

| The current core model classes like the TaskAssigningSolution, Task and User might change in future releases.

###### Linking the human tasks inputs with the labels

A simple approach for labeling tasks with business related information is implemented using the task inputs configuration. The following image shows an example of such a configuration.

Figure 121. Skills and affinities configuration

The example above links the process variable "variableWithTheSkills" with the task input name "skills", and the corresponding value will be processed by the "DefaultTaskDataSkillsValueExtractor" and automatically associated with the label name SKILLS.

This mechanism can be used for any other user provided LabelValueExtractor.

###### Custom extractors

Installations that require the definition of customized LabelValueExtractors can add them by providing their implementations in the customized KJARs with the UserSystemIntegration implementation or the Solver configuration.

1. Add a component in the specified KJAR that implements the following interface:

   org.kie.server.api.model.taskassigning.data.LabelValueExtractor

   Note: Ensure that the following dependency is added to the given KJAR:

    <dependency>
      <groupId>org.kie.server</groupId>
      <artifactId>kie-server-api</artifactId>
      <version>corresponding version</version>
      <scope>provided</scope>
    </dependency>

2. Declare the component implementation by using the Java standard service provider mechanism in the following resource:

   project_home/src/main/resources/META-INF/services/project_home/src/main/resources/META-INF/services/org.kie.server.api.model.taskassigning.data.LabelValueExtractor

When configured, the LabelValueExtractor will be processed accordingly.

The following example shows a custom LabelValueExtractor:

    import org.kie.server.api.model.taskassigning.data.LabelValueExtractor;
    import org.kie.server.services.taskassigning.user.system.api.User;

    public class UserExampleValueExtractor implements LabelValueExtractor<User> {

       public Class<User> getType() {
           // consider this extractor for processing users information.
           return org.kie.server.services.taskassigning.user.system.api.User.class;
       }

       public String getLabelName() {
           return "PASSPORT";
       }

       public int getPriority() {
           return 1;
       }

       public Set<Object> extract(User source) {
           Map<String, Object> attributes = source.getAttributes();
           Object value = attributes != null ? attributes.get("passport_number") : null;
           return value != null ? new HashSet<Object>(Collections.singleton(value)) : null;
       }
    }

Ensure that the following dependency is added to the specified KJAR:

    <dependency>
      <groupId>org.kie.server</groupId>
      <artifactId>kie-server-services-task-assigning-user-system-api</artifactId>
      <version>corresponding version</version>
      <scope>provided</scope>
    </dependency>

| Extractors for processing the human tasks information must use the class org.kie.server.api.model.taskassigning.TaskData as source type.

| The current core model classes like the TaskAssigningSolution, Task and User might change in future releases.

#### 7.17.3. Integration alternatives

System integrators usually consume the human tasks available in the Process Runtime kie-server for different purposes. One example is the Business Central "Task Inbox" in this case, Business Central acts as an "integrator" which means that the human tasks are consumed from the Process Runtime kie-server by using the kie-server queries APIs and applying different filtering criterias. Finally these tasks are listed in the "Task Inbox" UI, etc. In this way, Business Central is decoupled from the Process Runtime kie-server, etc.

The next topics present a set of queries similar to queries used by the Business Central "Task Inbox". These queries might facilitate integrations in cases where the task assigning integration is enabled.

##### 7.17.3.1. Task Assigning Human Tasks Query

This query facilitates the consumption of the available human tasks. The task can integrate additional information depending on the query variant. It is up to the "integrator" to select the query variant that best supports it’s needs.

###### Filtering parameters

The available filtering parameters are defined in the following kie-server-api enums:

    org.kie.server.api.model.definition.TaskField
    org.kie.server.api.model.taskassigning.PlanningTaskField

Both classes are found in the following maven artifact:

    <dependency>
        <groupId>org.kie.server</groupId>
        <artifactId>kie-server-api</artifactId>
    </dependency>

The following table shows the parameter name and the expected type.

Parameter | Type | Description
--- | --- | ---
ACTIVATIONTIME | Date | Time when this task was activated.
ACTUALOWNER | String | Actual owner assigned to this task - only set when task is claimed.
CREATEDBY | String | User who created this task.
CREATEDON | Date | Date when task was created.
DEPLOYMENTID | String | Deployment id this task is part of, typically the KIE Server container.
DESCRIPTION | String | Description of the task if any.
DUEDATE | Date | Due date set on this task if any.
NAME | String | Name of the task.
PARENTID | Long | Parent task id if any.
PRIORITY | Integer | Priority of the task.
PROCESSID | String | Process definition id that this task belongs to.
PROCESSINSTANCEID | Long | Process instance id that this task is associated with.
PROCESSSESSIONID | Long | KieSession id used to create this task.
STATUS | String | Current status of the task.
TASKID | Long | Identifier of task.
WORKITEMID | Long | Identifier of work item assigned on process side to this task id.
PTTASKID | Long | Same value as TASKID.
ASSIGNEDUSER | String | Same value as the ACTUALOWNER for published tasks.
PUBLISHED | Integer | Indicates if the task is published. For example "published = 1" can be used as filtering criteria in cases of filtering by the task that are currently assigned by the task assigning integration.

###### Querying the human tasks as TaskData instances

This query execution variant enables getting the result values as instances of:

    org.kie.server.api.model.taskassigning.TaskData

The following example shows how to use this variant:

Example 1)

    // Create the kie-server query services client.
    QueryServicesClient queryServices = createQueryServicesClient();

    // Set the filtering and ordering criteria and consider only the currently published tasks.
    QueryFilterSpec filter = new QueryFilterSpecBuilder()
        .equalsTo(TaskField.STATUS.toString(), "Reserved", "InProgress", "Completed")
        .equalsTo(PlanningTaskField.PUBLISHED.toString(), 1)
        .oderBy(TaskField.TASKID.toString(), true)
        .get();

    // Execute the query
    List<TaskData> result = queryServices.query(TaskAssigningQueries.JBPM_HUMAN_TASKS_QUERY,
                                                TaskAssigningQueries.TASK_DATA_QUERY_MAPPER,
                                                filter,
                                                0,    // staring page
                                                30,   // page size
                                                TaskData.class);

In this case, only the tasks currently assigned by the task assigning integration will be considered. This is the usual scenario when task assigning integration is enabled, because it is expected that the tasks are consumed and executed accordingly with the generated planning.

| The task inputs and potential owners are not loaded by this query.

Example 2)

    // Create the kie-server query services client.
    QueryServicesClient queryServices = createQueryServicesClient();

    // Set the filtering and ordering criteria and consider all of the tasks.
    QueryFilterSpec filter = new QueryFilterSpecBuilder()
        .equalsTo(TaskField.STATUS.toString(), "Ready”, Reserved", "InProgress", "Completed")
        .oderBy(TaskField.TASKID.toString(), true)
        .get();

    // Execute the query
    List<TaskData> result = queryServices.query(TaskAssigningQueries.JBPM_HUMAN_TASKS_QUERY,
                                                TaskAssigningQueries.TASK_DATA_QUERY_MAPPER,
                                                filter,
                                                0,    // staring page
                                                30,   // page size
                                                TaskData.class);

In this case all of the tasks will be considered but only the property assigned by the task assigning integration will have the TaskData.planningTask filled. It means that non assigned tasks or not yet managed by the task assigning integration might be included in the results. This alternative facilitates a more advanced processing of the "potential" tasks, however it is strongly encouraged to make available to the users only the tasks that are currently assigned by the task assigning integration . i.e. the ones with TaskData.planningTask != null otherwise the integration becomes senseless.

| The task inputs and potential owners are not loaded by this query.

See KIE Server API documentation for more information on how to create the KIE Server clients and the query API general functioning.

#### 7.17.4. Examples

##### 7.17.4.1. Credit dispute process

The following credit dispute process example is intended to show a simple use case where you can use the "skills" configuration to influence the way tasks are assigned according to the solver constraints and the process data.

Figure 122. Credit dispute process

###### Process start

When the process starts, the user is asked to complete the information in the following image. In particular, the credit card brand for which the dispute is related to and the preferred language for receiving the process notifications are requested. This information is used for assigning the process tasks.

Figure 123. Start credit dispute process form

###### Process configuration

The following image shows the process variables that are used for holding the card brand and language respectively.

Figure 124. Credit dispute process variables

The process start form populates these variables with the user inputs.

###### Resolve dispute task configuration

The following image shows the ResolveDispute task configuration, which establishes that the task input parameter skills is assigned with the value of the process variable cardType.

Figure 125. Resolve dispute task configuration

With this configuration, Red Hat build of OptaPlanner assigns this task to users that meet the following criteria:

1. Are in the user group CreditAnalyst

2. Have all of the skills configured in the task input parameter skills

###### Notify customer task configuration

The following image shows the NotifyCustomer task configuration, which establishes that the task input parameter skills is assigned with the value of the process variable language.

Figure 126. Notify customer task configuration

With this configuration Red Hat build of OptaPlanner assigns this task to users that meet the following criteria:

1. Are in the group ClientRelations

2. Have all of the skills configured in the task input parameter skills

3. Note that in this case the language selection is optional since the form field is not marked with "*" see the process start form, meaning that when no language is selected the task won’t have any configured skills. This implies that in such cases whatever users that are in group ClientRelations can be assigned to the task.

###### Process execution (example users)

Let’s assume that the following users configurations are used for executing the process.

users.properties file:

    john=analyst,admin,user,Accounting,PM,ClientRelations
    mary=analyst,admin,user,ClientRelations
    katy=analyst,admin,user,HR,CreditAnalyst
    maciek=admin,analyst,user,PM,HR,CreditAnalyst

skills.properties file:

    john=ES,EN                     (has skills in the Spanish and English languages)
    mary=ZH                        (has skills in the Chinese language)
    katy=CITI,MASTER               (has skills in the CITI and MASTER cards)
    maciek=VISA,AMERICAN_EXPRESS   (has skills in the VISA and AMERICAN EXPRESS cards)

###### Process execution (example instances)

With the preceding configurations the following execution scenarios are expected:

Process instance #1:

1) Start process

Figure 127. Start credit dispute process instance #1

2) ResolveDispute task

Figure 128. Resolve dispute task for process instance #1

The ResolveDispute task is assigned to the user maciek since it requires VISA skills.

| In real environments there might be many users with this skill. In this case Red Hat build of OptaPlanner assigns the new created task considering the optimized plan, which means that depending on the workload a different user could have been assigned.

3) NotifyCustomer task

Figure 129. Notify customer task for process instance #1

When the ResolveDispute task is completed, a new task NotifyCustomer is created and assigned to the user john because that task requires skills in Spanish.

Process instance #2:

1) Start process

Figure 130. Start credit dispute process instance #2

2) ResolveDispute task

Figure 131. Resolve dispute task for process instance #2

The ResolveDispute task is assigned to the user katy since it requires CITI skills.

3) NotifyCustomer task

Figure 132. Notify customer task for process instance #2

When the ResolveDispute task is completed, a new task NotifyCustomer is created and assigned to the user mary because that task requires skills in Chinese.

Process instance #3:

1) Start process

Figure 133. Start credit dispute process instance #3

2) ResolveDispute task

Figure 134. Resolve dispute task for process instance #3

The ResolveDispute task is assigned to the user katy because that task requires skills in the MASTER card.

3) NotifyCustomer task

Figure 135. Notify customer task for process instance #3

When the ResolveDispute task is completed, a new task NotifyCustomer is created and assigned to the planninguser because none of the users has the required skills in Hindi. In this case, an external interaction is required to determine the best suited user to complete the task. The planinguser must perform this action by delegating the task.

| The planninguser assignment is used to cover edge cases and should not be part of the modelling strategy. In the preceding example, if it is known that no user will have skills in Hindi. A similar but softer constraint can be configured by using affinities.

##### 7.17.4.2. Customized User System Service

For creating a custom user system service implementation follow these steps:

1) Create a KJAR project structure

2) Add the following dependency

    <dependency>
      <!-- Kie Server, OptaPlanner, or any other product dependencies must use provided scope -->
      <groupId>org.kie.server</groupId>
        <artifactId>kie-server-services-task-assigning-user-system-api</artifactId>
        <version>configure the proper version number aligned with the target kie-server</version>
        <scope>provided</scope>
    </dependency>

3) Provide your UserSystemService implementation, see the following example:

    public class MyDBUserSystemService implements UserSystemService {

        private DataSource dataSource;

        public String getName() {
            return "MyDBUserSystemService";
        }

        public void start() {
            String dataSourceName = System.getProperty("org.example.DBUserSystemService.ds",
                                                       "java:jboss/datasources/ExampleDS");
            try {
                InitialContext initialContext = new InitialContext();
                dataSource = (DataSource) initialContext.lookup(dataSourceName);
            } catch (NamingException e) {
                 // throw an exception if there are unrecoverable errors that prevent
                 // the service to start.
                throw new DBUserSystemServiceException("Unable to find data source under name " +
                                                       dataSourceName, e);
           }
        }

        public void test() throws Exception {
             // test your database queries etc.
        }

        public List<User> findAllUsers() {
            try (Connection conn = dataSource.getConnection()) {
                List<User> myUsers;
                // query the users information from the database.
               return myUsers;
           } catch (SQLException e) {
               throw new DBUserSystemServiceException("An error was produced finding all users: " +
                                                      e.getMessage(), e);
           }
       }

        public User findUser(String userId) {
            if (userId == null) {
                return null;
            }
            try (Connection conn = dataSource.getConnection()) {
                User user;
                // query the user information from the database.
                return user;
            } catch (SQLException e) {
              throw new DBUserSystemServiceException("An error was produced finding user: "+
                                                      e.getMessage(), e);
            }
        }
    }

4) Add the following resource to the project and declare your user system service provider class on it.

    src/main/resources/META-INF/services/org.kie.server.services.taskassigning.user.system.api.UserSystemService

    org.example.MyDBUserSystemService

Finally for using it in the Planning kie-server follow these steps:

1) Build your KJAR and be sure the corresponding maven generated artifact is installed in the maven repository used by your Planning kie-server.

2) Add a datasource configuration to your Planning kie-server pointing to the target DB (this step is only required for the example above) For example with JNDI name java:jboss/datasources/db-user-system-datasource

3) Finally add the following items to the Planning kie-server configuration file:

    <server>
    ...
    <system-properties>
      <property name="org.kie.server.taskAssigning.userSystem.name"
                value="MyDBUserSystemService" />
      <property name="org.kie.server.taskAssigning.userSystem.container.id"
                value="my-db-user-system-container" />
      <property name="org.kie.server.taskAssigning.userSystem.container.groupId"
                value="your KJARs groupId" />
      <property name="org.kie.server.taskAssigning.userSystem.container.artifactId"
                value="your KJARs artifactId" />
      <property name="org.kie.server.taskAssigning.userSystem.container.version"
                value="your KJARs version number" />
      <property name="org.example.DBUserSystemService.ds"
                value="java:jboss/datasources/db-user-system-datasource" />
    </system-properties>
    ...
    </server>