środa, 29 marca 2017

Get ready for jBPM 7 ... migrate from 6.5 to 7

Yes, that is correct - it's time to get ready for jBPM 7!!!

as part of preparation for final release of community version 7, I'd like to share some thoughts on how to move to it from 6.5.

First of all, the big change that is in version 7 is the separation between authoring/management and runtime. There is no execution engine in workbench any more and obviously there is no REST/JMS endpoints for it either. Though there is still REST api that covers:

  • repository and project management (including maven builds)
  • KIE Server controller
both are in version 6.5 as well and they have not changed much and are expected to be backward compatible.

Focus of this article will be on migrating from 6.5 workbench (as execution server) to 7.0 workbench (as authoring and management) and kie server (as execution server).

Let's put this article in some context, a very basic to keep it simple but should be enough to understand the concepts:
  • single workbench installation running on WildFly
  • single project deployed to execution engine in workbench - org.jbpm:HR:1.5
  • number of process instances started and active in different activities
The goal of this exercise is to make sure we can stop 6.5 "migrate" and start 7 and these process instances can move on.

Prepare for migration

First step before we shutdown version 6.5 is to configure Server Template for the coming version 7 and KIE Server

Here we define server template with name "myserver" that has single container configured "org.jbpm:HR:1.5". The name of the container is important as it must match the deployment id of the project deployed in workbench execution server. And this container is in started state.

As can be seen, there are no remote server attached to it, that's normal as currently workbench is responsible for runtime operations.

Now it's time to shutdown workbench's WildFly server...

Migrate workbench

Once the workbench is stopped it's time to migrate it to version 7 (at the time of writing latest one was Beta8). We are going to reuse same WildFly instance for new version of the workbench, so:
  • Download version 7 of kie-wb for WildFly 10. 
  • Move the workbench (6.5) from deployments directory of the WildFly server
  • Copy new war file into deployments directory - no modification to war file are needed - remember there is no runtime thus there is no persistence.xml to be edited :)
  • remove .index directory that was created by version 6.5 - this is required because version 7 comes with upgraded version of Lucene that is not compatible with one used in 6.5 - don't worry assets will be indexed directly after workbench starts
There is one extra step needed - to add new login module to security domain used by workbench - this is to allow smooth integration with KIE Server on behalf of user logged in to workbench. Just add one line (one marked in red) to standalone[-full].xml

<security-domain name="other" 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>
<login-module code="org.kie.security.jaas.KieLoginModule" flag="optional" module="deployment.kie-wb.war"/>
      </authentication>
</security-domain>
module  (part in bold) should point to the actual name of the war file you copied to deployments folder.

That's it, now it's time to start WildFly with workbench running version 7...

./standalone.sh
... yes, we can start it with default profile as there is no runtime in it (mainly JMS) so there is no need for full profile any more. But you can still use standalone-full.xml as server profile, especially if you have done any other configuration changes in it - like system properties, security domain, etc.

After a while, workbench is up and you can logon to it the same way you used to with 6.5.

Once logged in you can navigate to Deploy -> Execution Servers and the server template defined before the migrations should be there.
When you go to Process Definitions or Process Instance they will be empty as there is no KIE Server connected to it ... yet.

Migrate data base

As of major version, there have been some changes to the data base model that must be applied on data base that was used by version 6.5. jBPM comes with upgrade scripts as part of jbpm installer distribution (alternatively you can find those scripts in github). They are split into data base and version that they upgrade (from -> to)

An example from github:
jbpm-installer/src/main/resources/db/upgrade-scripts/postgresql/jbpm-6.5-to-7.0.sql

So this means that the upgrade script is for PostgreSQL db and provides upgrade from 6.5 to 7. Same can be found for major data bases supported by jBPM.

Logon to the data base and execute the script to perform migration of the data model.

Configure KIE Server

Last step is to configure brand new KIE Server version 7. A separate WildFly instance is recommended for it (especially for production like deployments) to separate authoring/management from runtime servers so they won't affect each other.

Most important is to configure WildFly server so it has:
  • same security domain as instance hosting workbench
  • same data sources that point to the active db as had 6.5 workbench 
  • and possibly other execution related configuration 
NOTE: Extra note about security is that users who are going to use workbench to interact with KIE Server (like starting processes, completing tasks) must have kie-server role assigned - security domain that is used by KIE Server.

KIE Server can be started with following command:
./standalone.sh
 --server-config=standalone-full.xml 
-Djboss.socket.binding.port-offset=150 
-Dorg.kie.server.id=myserver 
-Dorg.kie.server.controller=http://localhost:8080/kie-wb/rest/controller 
-Dorg.kie.server.location=http://localhost:8230/kie-server/services/rest/server 
-Dorg.kie.server.persistence.dialect=org.hibernate.dialect.PostgreSQLDialect 
-Dorg.kie.server.persistence.ds=java:jboss/datasources/psjbpmDS

Explanation of each line (skipping first line as it's command to start server):
2. select WildFly server profile to be used - requires full as KIE Server comes with JMS support
3. port offset to avoid port conflicts when running on same machine as workbench
4. server id that must match server template name defined in workbench
5. controller location - workbench URL with /rest/controller suffix
6. kie server location - actual location of the kie server (it must include port offset) 
7. hibernate dialect to be used
8. JNDI name of the data source to be used

NOTE: If the kjar was using singleton strategy then file that keeps track of ksession id of that project should be copied from workbench (WILDFLY_HOME/standalone/data/org.jbpm/HR/1.5-jbpmSessionId.ser) to same location in KIE Server's WildFly instance. This is important when you have facts in ksession or timers)

Once server is started, it will connect to workbench and collect list of containers to be deployed (in our case it's just one org.jbpm:HR:1.5)


KIE Server is now connected and ready for execution, you can find it in Deploy -> Execution Servers where it should be now visible as active remote server:

And when navigating to Tasks or Process Instances you should find your active instances left from 6.5

And that's it, now you're ready to take advantage of new features coming in 7 without a need of leaving your 6.5 work behind :)

środa, 1 marca 2017

Prepare for future ... KIE Server Router extension

KIE Server Router was built to cover two main areas:

  • hide the complexity of many KIE Server instances hosting different projects (kjars)
  • aggregate information from different KIE Servers regardless if they share the same db or host the same projects (kjars)
As described in previous articles, it can find the correct KIE Server instance for the incoming request based on container information that is sent through router. So the basic logic is that router keeps information (routing table) that have following information:
  • container id mapped to KIE Server location (url)
  • container alias mapped to KIE Server location (url)
  • server id mapped to KIE Server location (url)
in the context of this article, only first two are relevant. They are used to find the right server (or one of them) to forward the requests to.

The KIE Servers (Kjar 1 and Kjar 2) can have as many instances as they need that will be connected to the same db and will use the same set of containers deployed to them.

Whenever new request comes in, router will try to find if it contains container information and if so will attempt to find the route to the server that supports it. The situation is very simple if the request comes with container id (as opposed to container alias). As container ids are unique (and should be versioned to provide maximum flexibility) so the look up of the route is easy - just get it from routing table.
A bit more complex scenario is when the alias is used. Obviously this is more appealing to end users (client apps) as they don't have to change the URL whenever new container is deployed. So instead of using container id in the URL, container alias can be used to make the client less coupled with the constantly changing environment. 
By default KIE Server Router deals with container aliases same way as for container ids. Looks them up in the routing table to find the server location. Then it's the individual KIE Server that is responsible to find out concrete container that should be used to deal with that request. That is perfectly fine as long as there is no alias shared across different KIE Server - by different I mean KIE Server that host different kjars (usually different versions of the kjar).

As illustrated at the above diagram in such case, Kjar 2 should then take over entire responsibility for given container alias and host both versions of the project. As soon as it up and running the Kjar 1 server should be removed and then the Kjar 2 takes over entire load. 

This architecture promotes reusability of the runtime environment for the same domain - usually the version of given project are incremental updates that stays in the same domain. So that is what is available by default and the logic to find the proper container is within the KIE Server itself.

... but real world is not as simple ...

There are more options for deployments that would then put more responsibility in the KIE Server Router instead. Like for example taking the action to find out the latest container for an alias across all available containers. For example, if we want our clients to always start with latest available version of a process then client will use alias for container and router should resolve it before forwarding to KIE Server. That would mean that the architecture is that each KIE Server hosts single kjar and each version will bring in new KIE Server instance connected to the router but all of them will share the same alias.

The above setup is not covered by default in KIE Server router because the alias can be resolved to different servers that might not have the kjar deployed that given request is targeting. To allow to cover this use case KIE Server Router was enhanced to allow certain components pluggable:
  • ContainerResolver - component responsible for finding the container id to be used when interacting with backend servers
  • RestrictionPolicy - component responsible for disallowing certain endpoints from being used via KIE Server Router
  • ConfigRepository - component responsible for keeping KIE Server Router configuration, mainly related to the routing table
Since KIE Server Router can run in various environments these components can be replaced or enhanced compared to the defaults. For instance to support the described scenario - router to be responsible to find the latest container and then forward it to that kie server. This can be done by implementing custom ContainerResolver and plug it into the router. 

Implementations are discovered by router via ServiceLoader utility so the jar archives bringing in the new implementation need to have included service descriptor:
  • ContainerResolver 
    • META-INF/services/org.kie.server.router.spi.ContainerResolver
  • RestrictionPolicy
    • META-INF/services/org.kie.server.router.spi.RestrictionPolicy
  • ConfigRepository
    • META-INF/services/org.kie.server.router.spi.ConfigRepository
A sample implementation of all these components can be found in this project at github.

Since default KIE Server Router is ran as executable jar, to provide it the extensions the execution needs to slightly change:

java -cp LOCATION/router-ext-0.0.1-SNAPSHOT.jar:kie-server-router-proxy-7.0.0-SNAPSHOT.jar org.kie.server.router.KieServerRouter

once the server is started you will see log output stating what implementation is used for various components:

Mar 01, 2017 1:47:10 PM org.kie.server.router.KieServerRouter <init>
INFO: KIE Server router repository implementation is InMemoryConfigRepository
Mar 01, 2017 1:47:10 PM org.kie.server.router.proxy.KieServerProxyClient <init>
INFO: Using 'LatestVersionContainerResolver' container resolver and restriction policy 'ByPassUserNotAllowedRestrictionPolicy'
Mar 01, 2017 1:47:10 PM org.xnio.Xnio <clinit>
INFO: XNIO version 3.3.6.Final
Mar 01, 2017 1:47:10 PM org.xnio.nio.NioXnio <clinit>
INFO: XNIO NIO Implementation Version 3.3.6.Final
Mar 01, 2017 1:47:11 PM org.kie.server.router.KieServerRouter start
INFO: KieServerRouter started on localhost:9000 at Wed Mar 01 13:47:11 CET 2017


So that would be all for this article. Stay tuned for more updates and hopefully more out of the box implementations for KIE Server Router.

piątek, 24 lutego 2017

Enhanced KIE Server Router and Workbench integration

After KIE Server Router introduction there was quite interesting feedback especially regarding integration with workbench. Main point identified was the extra management needed when KIE Servers run in managed mode. This extra management was to setup (or more configure as router self register itself in the controller) to deal with all possible containers that backend KIE Servers could use.

So to put it straight, let's look at one scenario:

  • single KIE Server Router
  • two KIE Servers with unique server ids (pointing to different server templates in workbench)
    • hiring
      • hosting hiring container
    • evaluation
      • hosting evaluation container
  • single workbench with KIE Server controller

So with this setup, upon start KIE Server router will self register it in the controller but the servlet template will not have any containers defined. What impact does it produce? It means that workbench integration with KIE Server will not know how to construct data objects when interacting with it. In most of the cases it will simply say - no way to connect to KIE Server.
So to solve that, administrator would have to manually define all containers in the KIE Server Router's server template that are behind the router. This might work for simple cases where number of containers does not change too often but if the environment is much more dynamic it becomes quite an issue...

To address this out of the box, KIE Server Router is now equipped with logic to notify the controller about containers from the backend KIE Servers. This is done automatically whenever KIE Server deploys or undeploys a container. That is then directly registered in server template and can be used right of in workbench.

Here is how it actually works


Thanks to this integration between router and controller, there is no more manual intervention needed from the administrator side whenever new KIE Servers or new containers are added to be managed by the router.


Another (related to this) feature was added as well, this time to the integration between KIE Server and the Router. Till know KIE Server was only attempting to notify router when it starts. Though when at that time router was not available KIE Server didn't retry to notify it. That could lead into situations where server was up but router was not aware of it. Enhanced integration is that KIE Server will schedule retries (with default 10 seconds interval) to constantly try to notify router. This way as soon as router comes up it will receive notification from KIE Server and then register it (and its containers) in workbench.

Small features but makes the integration much easier and reliable.

Special thanks goes to Karel who lead the QE test day for KIE Server, well done Karel and the team!

czwartek, 16 lutego 2017

Linked process instance images

In one of the previous posts I described how to retrieve images of process instance from the runtime environment. Now I'd like to share small but helpful improvement in that area. Links between process instances that follow parent child relationship. To put it more in BPMN2 context those processes that use reusable subprocess (call activity).

This very simple process uses call activity to invoke another process instance that is linked to this one. In runtime after "test" activity is invoked there will be two process instances:

  • parent process instance that consists of call activity node













  • child process instance that was initiated by the call activity 















So this is what you could do already, so where is the improvement? It's this small '+' sign that allows to link between these two process instances. And this does work for both active and completed process instances.

A more complete showcase can be seen below



Short article but nice feature :)

piątek, 10 lutego 2017

jBPM 7 - case management security

Case management puts additional requirements on business automation. In many cases it's much more domain specific than business process management and thus will then have different (or better would be to say - extended) needs. This is no different when it comes to security.

Cases come with so called case roles. These are generic participants that will be involved in case handling. These roles can be assigned to user tasks or used as contact references. Though they are not defined in cases as concrete users or groups of users. Case roles are on case definition level to make the case definition independent of the actual actors involved in given case instance.

Case instances in turn, are those that are focused on individuals that will actually do the work as part of case handling. To provide this required flexibility case management in jBPM comes with case role assignments that allow to provide actual actors or groups for given role. Case role assignment can be given at the time case instance is started or can be set on already active case instance.

Note: Case role assignment can be modified at any time as long as case instance is active though it will not have effect on tasks already created based on previous role assignment.

General recommendation is to always start with case role assignments when starting a case instance as this will prevent situations of assigning tasks to not the correct owners.

How does it work?


By default case instance security is enabled. It does protect each case instance from being seen by users who do not belong to a case in anyway. In other words, if you are not part of case role assignment (either assigned as user or a group member) then you won't be able to get access to the case instance.  This applies to:

  • access to individual case instance 
  • access to case instance details like
    • case file
    • case stages
    • case milestones
  • queries for case instances
There is one situation when the case instance security will not take any effect - it is where there are no case roles defined at all. That essentially disables the security as there is no information to base authorisation on. 

Authorisation can also be turned off by system property: org.jbpm.cases.auth.enabled when set to false.

Above access is just one part of the security for case instances. In addition, there is case instance operations that can be restricted to case roles. Here is the list of currently supported case instance operations that can be configured:
  • CANCEL_CASE
  • DESTROY_CASE
  • REOPEN_CASE
  • ADD_TASK_TO_CASE
  • ADD_PROCESS_TO_CASE
  • ADD_DATA
  • REMOVE_DATA
  • MODIFY_ROLE_ASSIGNMENT
  • MODIFY_COMMENT
by default three of these operations:
  • CANCEL_CASE
  • DESTROY_CASE
  • REOPEN_CASE
are protected with following roles:
  • owner
  • admin
again, these are case roles so based on case role assignments can differ between case instances. Thus allowing maximum flexibility in how to utilise them.

security for case operations is configurable via simple property file called case-authorization.properties that should be available at root of the class path upon start of the case application. Format of this file is extremely simple:
OPERATION=role1,role2,roleN

Some might say that it's too generic to have single config file for all possible case definitions but that's a way of promoting thinking about case management as domain specific and to build tailored application where single configuration for case role security is certainly enough. Moreover (as everything in jBPM) AuthorizationManager for case security is pluggable so if you need any specific handling you can just put your own piece of code to do so.

And at the end, let's see this working in Order IT hardware application, in particular how can we easily restrict access to only involved people or certain actions.


That's it folks, stay tuned and share your feedback!

środa, 25 stycznia 2017

KIE Server Router integrated with workbench

In one of the recent posts I presented KIE Server Router to allow to scale to more instances of KIE Servers where there is one smart router that can:

  • find the right servers to deal with requests
  • aggregate data from various servers
  • remove burden from clients to know the location of KIE Servers
  • and more...

With all that it's time to look into using KIE Server Router with workbench to utilize its UI capabilities to work with processes and tasks. Overall idea is to use the router as any other KIE Server so that means:
  • router will connect to workbench controller
    • notifies when started
    • notifies when shutting down
  • server template is required for the router - if none created before it will self-register itself
  • all containers deployed behind the router must be in router's server template so all of them can be used in terms of forms, images and data
Though router acts like a KIE Server from workbench point of view it does not allow to perform KIE Server management operations like creating containers or upgrading them etc. These should be still managed in the same way as without router.

Workbench will see the router as regular KIE Server and thus will make the exact same features available for it, like starting processes, working with user tasks etc. So let's imagine following scenario:

  • single workbench
  • single router
  • KIE Server for HR process - running on dedicated server instance (:8180 port)
  • KIE Server for Evaluation process - running on dedicated server instance (:8280 port)
KIE servers are running in unmanaged mode with predefined versions of kjars to be deployed, one per KIE Server. These KIE Servers are then connected to router. In turn router is configured to connect to controller once started. In workbench there is a single KIE Server Router server template configured with both kjars (containers) configured and started.

Here you can see how it works


As can be seen in the screen cast, all normal operations are available to the users. Starting processes that are actually executed on different servers (that in real scenario will be on completely different machines) without any hassle. Same goes for retrieving various information like active instances, showing process instance image, work with tasks. All goes via router that decides to what server the request should be forwarded.

Moreover, it aggregates the results for queries e.g. process instance, process definition or tasks so there is no need to go over individual servers to figure out what instances are running and to get the details of them. Even dashboard does work via router, though it still has some issues as it expects to have a single row instead of aggregate of all servers so this is still something to address...

The only limitation at the moment is sorting capabilities of the aggregated results. In general router is capable of doing aggregate sort but the problem here is that the data returned when used through workbench are in raw format and thus router has not information what field is what and thus sorting is in the way that individual servers returned. Though it does support paging in normal fashion.

... if you want to give it a try yourself

there is small trick to start it in particular sequence:

  • workbench first
    • ./standalone.sh
  • router (without the controller property)
    • java -jar target/kie-server-router-proxy-7.0.0-SNAPSHOT.jar
  • kie servers (with router property)
    • /standalone.sh --server-config=standalone-full.xml -Djboss.socket.binding.port-offset=100 -Dorg.kie.server.id=hr-server -Dorg.kie.server.location=http://localhost:8180/kie-server/services/rest/server -Dorg.kie.server.router=http://localhost:9000
  • restart router with controller property
    • java -Dorg.kie.server.controller=http://localhost:8080/kie-wb/rest/controller -jar target/kie-server-router-proxy-7.0.0-SNAPSHOT.jar
this is needed when running in memory data base as upon connection of the router to controller, it will push queries to the connected KIE Server to register so workbench queries could work as expected. Since the router is connecting to controller it will the forward these queries to all connected kie servers to register these queries in there. As they are running with in memory db these queries are constantly dropped and thus must be registered again. With real use case these are going to be registered once and won't be really relevant to have the sequence as above.

środa, 18 stycznia 2017

Distribute tasks wisely ... pluggable task assignments jBPM7

User interaction in business processes is one of the most important aspects to make sure that the job is done. But not only that, it should make sure that the job is done:

  • on time
  • by proper actors
  • in least time possible
  • and more...
User tasks in business processes can be assigned either to:
  • user(s) - individuals that are known at the time of task creation - one or more
  • group(s) - groups/roles that are known at the time of task creation - one or more groups
  • users or groups references as process variables
With this users are already equipped with quite few choices that allow to manage user tasks efficiently. So let's review simple scenario:

Here is the simplest process as it can be - single user task.
Such a task can be assigned (at design time - when process is created) to:
  • individuals via ActorId property - it supports comma separated list to specify multiple actors
  • groups via GroupId property - it supports comma separated list to specify multiple groups


... use single actor

So if the task is assigned to single actor then when task is created it:
  • will be assigned directly to that actor - actual owner will be that actor
  • will be moved to Reserved state
  • no one else will be able to work on that task anymore - as it is in reserved state
So that seems like a nice approach, but in reality it will constrain users too much because to change the actor you have to change the process definition. And in many cases there is a need for more users to be able to deal with certain tasks instead of just a single person.

... use multiple actors

To solve that you can use approach with multiple actors (as this is supported to specify set of users as comma separated list). So what will happen then?
  • task will not be assigned to any individual as actual owner as there is no way to tell which one should be selected
  • task will be available to all actors defined in process definition on that task
  • task will be moved to Ready state
  • user to be able to work on task will have to explicitly claim the task
So a bit of improvement but still relies heavily on individuals and manual claim process that can sometimes lead to inefficiency due to delays.

... use groups

naturally to go around the problem with individuals being assigned (as they come and go) better option would be to assign tasks to groups. When task is assigned to group it:
  • will not be assigned to any individuals as by nature group contains many members
  • will be available to all actors that belong to defined group(s) - it's resolved on the time of the query as task is assigned to group so changes to the group do not have to be synced with tasks
  • will be moved to Ready state
  • user to be able to work on task will have to explicitly claim the task
so this improves situation a bit but still have some issues ... manual claim and potential delays to pick tasks from the group "queue".

... use pluggable task assignment 

for this exact purpose, jBPM 7 comes with pluggable task assignment support to let you (or to be precise system) to distribute tasks according to various criteria. The criteria here are what makes the difference, as different business domains will have different ways of assigning tasks. Even different departments within the same organization will differ in that regard. 

So what is the task assignment here? In general this is the logic that will be used to find the best suitable candidate to take the task automatically. To carry on with the example, there is a process that is assigned to a singe group - HR. 
Task assignment strategy will then be invoked when a task is created and strategy can find the best actual owner for it. If it does such a task:
  • will be assigned to selected actor
  • will be moved to Reserved state
  • no one else will be able to work on this task any more 
but if the strategy won't be able to find any suitable candidate (should be rather rare case but still can happen) the task will fallback to default behavior as described above.

Assignment strategy can be based on almost anything that is valuable to the business to make a fact based and efficient decision. That means some strategies can be based on:
  • potential owners (as in this example)
  • task data (input variables)
  • task properties (name, description, project, etc)
  • time when task was created
  • external data not related to task itself

So that gives all the options to the users to build their own strategies based on the specific needs. But before going to the implementation (next article) let's look at...

... what comes out of the box

jBPM 7 comes with two assignment strategies out of the box
  • Potential owner busyness strategy - default
  • Business rules strategy
Potential owner busyness strategy
this strategy simply makes sure that least loaded actors from potential owner list will be selected. Strategy will work on both types of potential owners - users and groups but to be able to effectively find best match it needs to resolve groups to users. Resolve is done by UserInfo configured in the environment - please make sure you have one properly configured otherwise strategy will not work in most efficient way.

Name of the strategy to be used to activate:
PotentialOwnerBusyness




Business rules strategy
This strategy promotes the use of business rules as a way of selecting actual owners. Strategy does not come with any predefined rules but instead expect to be given the KJAR coordinates of the project to be used to perform assignment. The most important factor here is that any rule can be used and it supports dynamic updates of the rules as well by making use of KIE Scanner that can incrementally update knowledge base upon new version of the KJAR being discovered.

Name of the strategy to be used to activate:
BusinessRule

Configuration parameters supported:
  • org.jbpm.task.assignment.rules.releaseId
    • required parameter that points the GAV of the KJAR
  • org.jbpm.task.assignment.rules.scan
    • optional - pool interval for the scanner in case it should be enabled - same as KIE Scanner expects it - in milliseconds
  • org.jbpm.task.assignment.rules.query
    • optional - drools query to be used to retrieve results - if not given all Assignment objects are taken from working memory and first is selected if not empty


... not only on task creation

task assignment is invoked not only on task creation (though that will be the most common case) but it will also get involved when:
  • task is released - here the actual owner who releases the task is excluded from the assignment
  • task nomination
  • task reassignment (deadlines)
  • task forwarding
with that it should provide quite capable self assignment behavior when the strategy is tailored for given needs.

... how to use it

Task assignment is disabled by default and can be easily enabled by specifying system property:
-Dorg.jbpm.task.assignment.enabled=true

then selecting strategy is done by another system property:
-Dorg.jbpm.task.assignment.strategy=NAME OF THE STRATEGY

if org.jbpm.task.assignment.strategy is not given PotentialOwnerBusyness strategy is used by default.

To be able to properly resolve group members users need to select user info implementation by system property:

-Dorg.jbpm.ht.userinfo=db

this one will select data base as source of group members and thus will have to be configured additionally. KIE Server comes with example configuration file in
kie-server.war/WEB-INF/classses/jbpm.user.info.properties

where db queries should be specified how to find users of given group.

Optionally you can create userinfo.properties file in the same directory and specify the group to users mapping in following format:

#groups setup
HR=hr@domain.com:en-UK:HR:[maciek,engUser,john]
PM=pm@domain.com:en-UK:PM:[maciek]

this is only for test purposes. For real environment use either data base or ldap based UserInfo implementation.

That concludes the introduction of task assignment strategies that are completely pluggable. Next article will illustrate how to implement custom strategy.