jBPM5/Drools Apache Camel integration

 

After a few months I’m back with another useful, or maybe not, post about the integration between Apache Camel and Drools/jBPM5. I decided to write this post because 1) people are continuously asking about the last changes in the integration and 2) I already had a POC using the last Drools/jBPM5/Camel integration in my github account.

So, in this example I’m going to explain how to use jBPM5 together with Apache Camel but the same concepts and configuration can be applied to a Drools integration with Camel.

There are two ways to create the integration: programatically and using the Spring Framework. This post will only explain the first one but you can expect a new post about the jBPM5/Camel/Spring integration in the next days.

First we are going to need a BPMN file as the next one, which is really simple.

BPMN2 example

The fist step is create a StatefulKnowledgeSession as you usually do.

KnowledgeBuilder kbuilder = KnowledgeBuilderFactory.newKnowledgeBuilder();
kbuilder.add(ResourceFactory.newClassPathResource("com/wordpress/lucazamador/jbpm/Sample.bpmn"),
ResourceType.BPMN2);

if (kbuilder.hasErrors()) {
   if (kbuilder.getErrors().size() > 0) {
      for (KnowledgeBuilderError kerror : kbuilder.getErrors()) {
         System.err.println(kerror.getMessage());
      }
      throw new RuntimeException(kbuilder.getErrors().toString());
   }
}

KnowledgeBase kbase = kbuilder.newKnowledgeBase();
StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();

Once you created a StatefulKnowledgeSession we can start the configuration of the Apache Camel integration. As maybe you know, the drools-camel module internally uses the drools-grid module to execute the Drools Commands. These concepts were already explained in depth in a previous post, so maybe you would like to read the previous one to get more details. Or read the official documentation available at

First we need to instantiate a org.drools.grid.GridImpl object and register an org.drools.grid.service.directory.WhitePages service. This WhitePages service is the place where our grid services are registered, such the GridNodes.
Actually there are three WhitePages implementations available:

  • an implementation using JPA,
  • a remote WhitePage services
  • the classic HashMap services implementation, which is the one that is going to be used in this example.
GridImpl grid = new GridImpl();
grid.addService(WhitePages.class, new WhitePagesImpl());

After this we only have to create a GridNode with an identifier and register it on a JndiContext using the identifier that will be used to send the messages.

GridNode node = grid.createGridNode("node");
Context context = new JndiContext();
context.bind("node", node);

At this point the only remaining step is the registration of the previously created KnowledgeSession in the GridNode.

node.set("ksession1", ksession);

The grid-module configuration is done, so now we have to configure a Apache CamelContext object with their routes definitions. Remember than the CamelContext should be created using the org.apache.camel.util.jndi.JndiContext object were the GridNode was registered, otherwise the Drools Component wasn’t going to be able to obtain the knowledge sessions.

CamelContext camelContext = new DefaultCamelContext(context);

Ok, time to add a Camel Route, in this case a CamelRoute using the simplest and always efficient Direct Endpoint. It’s the simplest route out there, and this is because it was created for testing purpose.

RouteBuilder rb = new RouteBuilder() {
   public void configure() throws Exception {
      from("direct:test-with-session").to("drools://node/ksession1");
   }
};
camelContext.addRoutes(rb);

Once the route were created you are ready to start the Apache CamelContext using:

camelContext.start();

So far no more configuration is needed and you are ready to send messages to the CamelContext. How to send messages was covered more in depth, or at least that is what I remember, in the previous posts that now are outdated because of the grid configuration changes. But as a small hint, you can follow the next code to know how to send a Drools Command to the CamelContext.

StartProcessCommand startProcessCommand = new StartProcessCommand("org.jbpm.test", "process-instance-id");
List> commands = new ArrayList>();
commands.add(startProcessCommand);
BatchExecutionCommand batchExecutionCommand = CommandFactory.newBatchExecution(commands, "ksession1");

ExecutionResults response = (ExecutionResults) template.requestBody("direct:test-with-session",
batchExecutionCommand);
Long processInstanceId = (Long) response.getValue("process-instance-id");

SignalEventCommand signalEventCommand = new SignalEventCommand("continueSignal", null);
commands.clear();
commands.add(signalEventCommand);
batchExecutionCommand = CommandFactory.newBatchExecution(commands, "ksession1");
response = (ExecutionResults) template.requestBody("direct:test-with-session", batchExecutionCommand);

For more details you can take a look to the example code available at http://github.com/lucazamador/jbpm5-spring-camel-integration

And don’t forget to check the official documentation here

In the next post I’ll show how configure this using the Spring Integration, or maybe something more interesting.

1 thought on “jBPM5/Drools Apache Camel integration

  1. Suyash Patil

    im geting this error when i tried to run it any fix suggestions???

    ——————————————————————————-
    Test set: com.wordpress.lucazamador.jbpm.SpringIntegrationTest
    ——————————————————————————-
    Tests run: 1, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 1.792 sec <<< FAILURE!
    springIntegration(com.wordpress.lucazamador.jbpm.SpringIntegrationTest) Time elapsed: 1.743 sec <<< ERROR!
    java.lang.RuntimeException: unable to execute Action
    at org.jbpm.workflow.instance.node.ActionNodeInstance.internalTrigger(ActionNodeInstance.java:49)
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.trigger(NodeInstanceImpl.java:122)
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.triggerConnection(NodeInstanceImpl.java:185)
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.triggerCompleted(NodeInstanceImpl.java:150)
    at org.jbpm.workflow.instance.node.StartNodeInstance.triggerCompleted(StartNodeInstance.java:49)
    at org.jbpm.workflow.instance.node.StartNodeInstance.internalTrigger(StartNodeInstance.java:41)
    at org.jbpm.workflow.instance.impl.NodeInstanceImpl.trigger(NodeInstanceImpl.java:122)
    at org.jbpm.ruleflow.instance.RuleFlowProcessInstance.internalStart(RuleFlowProcessInstance.java:35)
    at org.jbpm.process.instance.impl.ProcessInstanceImpl.start(ProcessInstanceImpl.java:188)
    at org.jbpm.workflow.instance.impl.WorkflowProcessInstanceImpl.start(WorkflowProcessInstanceImpl.java:302)
    at org.jbpm.process.instance.ProcessRuntimeImpl.startProcessInstance(ProcessRuntimeImpl.java:150)
    at org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:120)
    at org.jbpm.process.instance.ProcessRuntimeImpl.startProcess(ProcessRuntimeImpl.java:112)
    at org.drools.common.AbstractWorkingMemory.startProcess(AbstractWorkingMemory.java:1090)
    at org.drools.impl.StatefulKnowledgeSessionImpl.startProcess(StatefulKnowledgeSessionImpl.java:297)
    at com.wordpress.lucazamador.jbpm.SpringIntegrationTest.springIntegration(SpringIntegrationTest.java:17)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
    at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
    at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:53)
    at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:123)
    at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:104)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:164)
    at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:110)
    at org.apache.maven.surefire.booter.SurefireStarter.invokeProvider(SurefireStarter.java:175)
    at org.apache.maven.surefire.booter.SurefireStarter.runSuitesInProcessWhenForked(SurefireStarter.java:107)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:68)
    Caused by: [Error: System.out.println("script 1 executed"): Class org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer can not access a member of class org.apache.maven.surefire.report.ConsoleOutputCapture$ForwardingPrintStream with modifiers "public"]
    [Near : {… System.out.println("script 1 e ….}]
    ^
    [Line: 1, Column: 1]
    at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:413)
    at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.optimizeAccessor(ReflectiveAccessorOptimizer.java:140)
    at org.mvel2.ast.ASTNode.optimize(ASTNode.java:158)
    at org.mvel2.ast.ASTNode.getReducedValueAccelerated(ASTNode.java:115)
    at org.mvel2.MVELRuntime.execute(MVELRuntime.java:87)
    at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:128)
    at org.mvel2.compiler.CompiledExpression.getValue(CompiledExpression.java:118)
    at org.mvel2.MVEL.executeExpression(MVEL.java:954)
    at org.jbpm.process.instance.impl.MVELAction.execute(MVELAction.java:94)
    at org.jbpm.workflow.instance.node.ActionNodeInstance.internalTrigger(ActionNodeInstance.java:47)
    … 44 more
    Caused by: java.lang.IllegalAccessException: Class org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer can not access a member of class org.apache.maven.surefire.report.ConsoleOutputCapture$ForwardingPrintStream with modifiers "public"
    at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
    at java.lang.reflect.Method.invoke(Method.java:588)
    at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.getMethod(ReflectiveAccessorOptimizer.java:1029)
    at org.mvel2.optimizers.impl.refl.ReflectiveAccessorOptimizer.compileGetChain(ReflectiveAccessorOptimizer.java:338)
    … 53 more

    Reply

Leave a comment