В
другой части серии «Советы и рекомендации по JBoss BPM Suite» мы поможем понять, как вы можете получить доступ или изменить переменную контекста процесса из правила в вашем проекте BPM.
Мы будем использовать простой демонстрационный проект, который можно найти в наших
демонстрационных коллекциях на github , который позволит вам просмотреть и поэкспериментировать с последним рабочим примером в установке JBoss BPM Suite.
Установку JBoss BPM Suite вам нужно будет настроить самостоятельно, но вы можете использовать наш
проект установки JBoss BPM Suite , чтобы избавить вас от проблем.
Цель
Основная цель этой статьи и демонстрационного проекта — показать вам, как именно разработать процесс, который использует правило, которое при его запуске получит доступ и изменит одну из переменных процесса. Эта связь между процессом и правилом является часто задаваемым вопросом.
Настройка
Начните с разархивирования репозитория демонстрационного проекта и скопируйте его в каталог проектов установки JBoss BPM Suite.
# Start by cloning project at # https://github.com/eschabell/demo-collections. # $ git clone [email protected]:eschabell/demo-collections.git $ cd demo-collections $ unzip niogit-rule-procvar.zip # Follow instructions and install JBoss BPM Suite # via https://github.com/eschabell/bpms-install-demo. # # Then copy the demo repository into the JBoss BPM Suite server. # $ cp -rv .niogit bpms-install-demo/target/jboss-eap-6.1/bin # Start the JBoss BPM Suite server. # $ ./bpms-install-demo/target/jboss-eap-6.1/bin/standalone.sh # Login with user 'erics' and password 'bpmsuite' to get started.
Now we can take a look at the process, how it is configured to be deployed by default, what the rule is, what we have to do to modify a process variable, and look at the output.
The initial output
Our process consists of a simple run through that prints a log statement at the first node, then runs a rule (which we want to modify a process variable), then a gateway where we decide if the rule fired or not, and then the path where the rule fired (we log that) or the path where the rule did not fire (we log that too).
Test process for rule modifying a process variable. |
What we want to test is that a rule with a Left Hand Side or Condition that evaluates to TRUE, will trigger its corresponding Right Hand Side or Action to print a log statement that the rule fired.
On our initial attempt we had a process that only had the first two nodes, then ended. We expected to see something like this in the logs if we ran three instances of the process:
17:29:46,315 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step 17:29:46,330 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule 17:29:46,315 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step 17:29:46,330 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule 17:29:46,315 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step 17:29:46,330 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule
What we ended up with was this:
17:29:46,315 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step 17:29:46,330 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule 17:29:46,315 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step 17:29:46,315 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step
At this point we modified the process you see above, adding two debug nodes that report if the rule fired or not, making the outcome clearer. We expected to see something like this in the logs if we ran three instances of the process:
20:51:22,491 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step 20:51:22,494 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Tested Rule 20:51:22,497 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Rule fired! 20:51:35,615 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step 20:51:35,618 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Tested Rule 20:51:35,621 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Rule fired! 20:51:43,312 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step 20:51:43,316 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Tested Rule 20:51:43,320 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Rule fired!
What we ended up with was this:
20:51:22,491 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step 20:51:22,494 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Tested Rule 20:51:22,497 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Rule fired! 20:51:35,615 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step 20:51:35,618 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Rule did not fire... 20:51:43,312 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Execute Java Step 20:51:43,316 INFO [stdout] (http-localhost/127.0.0.1:8080-2) Rule did not fire...
What happened to the rule firing the second and third time? Not only that, the rule never even triggers in the second and third time through, why?
To find out we need to look at the session strategy that is applied by default.
The deployment
Taking a closer look at how this process is deployed, we see that it makes use of the default session strategySINGLETON which means it will run all process instances in a single ksession.
Deployment by default is using SINGLETON runtime strategy |
This means that the process would put any facts into working memory and then run through our process and at the rule task it would evaluate the rule. This was the first time through an instance.
The second (and all consecutive) time through the working memory was not being modified so the rule is never evaluated, it just passes over it.
To fix this we need to make the process clearer, so we added a process variable to be updated when the rule fired, a gateway to check the process variable, and if set to log that the rules had fired. Remember, the rule firing sets the process variable.
Let’s see how that looks.
The rule
We took our initial stab at the rule by setting it up to always match the condition so that the action would fire:
rule "update-procvar" ruleflow-group "fire-always" when eval(true) then System.out.println("Tested Rule"); end
Remember with the single ksession the first time through it fired, but after that it never gets evaluated again. To fix this we will need to make sure that some form of object or fact is added into the working memory each time this process instance is run.
Luckily this is provided for in a rule task, where you can create Data Assignments and map your DataInputSets. This is done by selecting the rule task and expanding the Properties sidebar to show you that we have created afired variable and assigned it the value null, then we are inserting it into the working memory as our DataInputSet.
Mapping the fired variable into the working memory every time. |
import org.kie.api.runtime.process.WorkflowProcessInstance; rule "update-procvar" ruleflow-group "fire-always" when $pi: WorkflowProcessInstance() String() then $pi.setVariable("fired", "true"); end
$pi so we can work with it to access our process variable, then we have a check that will always succeed if there is a new
String object in working memory. Remember we insert a
fired object every time we enter this
rule task node?
This should cause the rule to evaluate and then using the
process instance we can set the process variable
fired to true, which is exactly the check that is done at the following gateway node.
Let’s run it a few times and see what happens?
The Output
Now that we have sorted out the issues and understand what it means to have a single ksession in which our rules will only fire on a new instance if there has been some fact change in the working memory, we are ready to test our solution.
This is what you will see when you run three instances of the demo process:
21:06:32,767 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step 21:06:32,774 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule 21:06:32,777 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Rule fired! 21:06:41,646 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step 21:06:41,654 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule 21:06:41,656 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Rule fired! 21:06:47,559 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Execute Java Step 21:06:47,565 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Tested Rule 21:06:47,567 INFO [stdout] (http-localhost/127.0.0.1:8080-5) Rule fired!
We hope you now understand how a process is deployed using a rule, how to access and update a process variable from a rule in your project, and can put this knowledge to use in your own projects.