5 Replies Latest reply on Apr 14, 2016 12:31 PM by ssoares

    jBPM 6.0 ksession clustering

    mpawlak

      Hello

       

      My application is based on jBPM 5 and because of some clustering problems I am testing jBPM 6 to replace the old version. I used example from jbpm-6-examples/rewards-basic at master · jsvitak/jbpm-6-examples · GitHub as a test platform.

      Unfortunately, as far as I have tested it, it still has issues with sharing the same KSession with multiple nodes.

       

      The RuntimeManager was set to use singleton strategy.

       

              RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()

                      .newDefaultBuilder()

                      .entityManagerFactory(emf)

                      .addAsset(ResourceFactory.newClassPathResource("rewards-basic.bpmn"), ResourceType.BPMN2)

                      .get();

       

                  environment.getEnvironment().set(EnvironmentName.USE_PESSIMISTIC_LOCKING, true);

              singletonManager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment);

              RuntimeEngine runtime = singletonManager.getRuntimeEngine(new Context() {

                  @Override

                  public Object getContextId() {

                      return singletonManager.getIdentifier();

                  }

              });

           KieSession ksession = runtime.getKieSession();

       

                  Map<String, Object> params = new HashMap<String, Object>();

                  params.put("recipient", recipient);

                  ProcessInstance processInstance = ksession.startProcess(

                          "com.sample.rewards-basic", params);

       

       

       

      The test is simple:

      1. Create first process on node 1

      2. Create second process on node 2

       

      And after step two, I always facing the same Hibernate exception as for jBPM 5:

      Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.drools.persistence.info.SessionInfo#1]

       

      On jBPM 5 I reloading the KSession from database, but I refering to it as workaround.

       

      My application has the requirement that the same process instance must be accessible by different users logged to different nodes. Processes have human task, are stateful and are considered to be long-running (days, months). Tasks are carried out quickly.

       

      So, my questions are:

      1. Can I use the same KSession on multiple nodes?

      2. If not, what are other mechanisms of jBPM 6 to synchronize processes' states between all nodes?

      3. If I use the different approach, will timers and events work in multiple nodes environment?

        • 1. Re: jBPM 6.0 ksession clustering
          jsvitak

          Hi Maciej,

           

          Thank you for using the example web app.

           

          I would prefer to use a different runtime manager (session strategy). Singleton runtime manager has its limitations. Especially in this case, where you need to use timers. Try the same with PerProcessInstance runtime manager. Using this, a dedicated ksession will be created for each process instance and so there will be separate contexts and no conflicts. The last session strategy is PerRequest, this one creates a ksession for each request.

           

          I also think that the two nodes using the same simple web example app are not aware of each other and so they may have a conflict in database. I have to check my example app code, it was written only for demo purposes. Maybe this app needs to check for existing ksession, and if necessary load it.

           

          Please also consider advantages of kie workbench. This web app provides an execution server. It synchronizes its configuration stored in VFS across all nodes of cluster. So the nodes are aware of each other and they replicate assets between themselves. You may run processes remotely in this execution server using REST or JMS apis. Their synchronization also takes care of necessary automatic load session from SessionInfo table, so there are no problems also with Singleton session strategy. But as I said before, PerProcessInstance should be more suitable for your use case.

           

          Hope that helps,

          Jiri

          • 2. Re: jBPM 6.0 ksession clustering
            mpawlak

            Hi Mr. Jiri

            Thank You for Your reply.

             

             

            I don't think that using Session per ProcessInstance strategy will solve the problem.

            E.g.:

            1. On node1 user1 starts processInstance (p1) creating session (s1).

            2. On node2 user2 pickups a task (t1) from p1 and ends it.

            3. On node1 user1 pickups another task (t2) from p1.

             

            If p1 will try to end t2 he will get an exception as noted above.

            It seems that you have to always reload your session before performing any task actions.

             

            Does KIE Workbench solve this issue by synchronizing sessions between nodes?

            • 3. Re: jBPM 6.0 ksession clustering
              jsvitak

              PerProcessInstance may not solve the current problem, but it may prevent the future ones, especially with timers/rule tasks.

               

              I haven't experienced such issues with kie workbench. So it probably reloads the session. (btw I'm not jBPM developer, so sorry that I can't say for sure).

               

              Hope that helps,

              Jiri

              • 4. Re: jBPM 6.0 ksession clustering
                swiderski.maciej

                Maciej Pawlak wrote:

                 

                Hello

                 

                My application is based on jBPM 5 and because of some clustering problems I am testing jBPM 6 to replace the old version. I used example from jbpm-6-examples/rewards-basic at master · jsvitak/jbpm-6-examples · GitHub as a test platform.

                Unfortunately, as far as I have tested it, it still has issues with sharing the same KSession with multiple nodes.

                 

                The RuntimeManager was set to use singleton strategy.

                 

                        RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()

                                .newDefaultBuilder()

                                .entityManagerFactory(emf)

                                .addAsset(ResourceFactory.newClassPathResource("rewards-basic.bpmn"), ResourceType.BPMN2)

                                .get();

                 

                            environment.getEnvironment().set(EnvironmentName.USE_PESSIMISTIC_LOCKING, true);

                        singletonManager = RuntimeManagerFactory.Factory.get().newSingletonRuntimeManager(environment);

                        RuntimeEngine runtime = singletonManager.getRuntimeEngine(new Context() {

                            @Override

                            public Object getContextId() {

                                return singletonManager.getIdentifier();

                            }

                        });

                     KieSession ksession = runtime.getKieSession();

                 

                            Map<String, Object> params = new HashMap<String, Object>();

                            params.put("recipient", recipient);

                            ProcessInstance processInstance = ksession.startProcess(

                                    "com.sample.rewards-basic", params);

                 

                 

                 

                The test is simple:

                1. Create first process on node 1

                2. Create second process on node 2

                 

                And after step two, I always facing the same Hibernate exception as for jBPM 5:

                Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [org.drools.persistence.info.SessionInfo#1]

                 

                This is because you loaded same ksession (from db) on two nodes and that is expected that they will fail with optimistic lock exception due to concurrently updating same entry in data base. So if you like to use singleton strategy then each node should use independent ksession instance - different db entries. By default singleton strategy should do that as it stores the ksession id on file system in temporary location. Depending on how you deploy the application it can be in various location but you can enforce it by setting system property to the desired location -Djbpm.data.dir=/some/location - this should be set to different location for every node.


                Maciej Pawlak wrote:

                 

                So, my questions are:

                1. Can I use the same KSession on multiple nodes?

                depends on strategy - no for singleton as it keeps session active all the time, yes for per process instance

                Maciej Pawlak wrote:

                 

                2. If not, what are other mechanisms of jBPM 6 to synchronize processes' states between all nodes?

                usually per process instance would be good choice for clustered environments as it will load and the dispose ksession on request basis eliminating possibility of concurrent access to ksession from multiple threads. That provides ksession state isolation as well, meaning all facts will be visible to single process instance. If that is not a requirement you'll be good with singleton or per request strategies as well, just make sure that ksession instance is not shared between nodes.

                 

                Maciej Pawlak wrote:

                 

                3. If I use the different approach, will timers and events work in multiple nodes environment?

                yes, just make sure that timer service is configured with quartz and db store for most reliable and efficient timer handling. See article on clustering of kie workbench here.

                 

                HTH

                • 5. Re: jBPM 6.0 ksession clustering
                  ssoares

                  I'm using jbpm 6.0.3,

                  I am experiencing a similar problem with her using singletonManager.

                  occurs Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [# org.jbpm.persistence.processinstance.ProcessInstanceInfo at.

                  I made the alterations to use @PerProcessInstance however happens a new exception Caused by: java.lang.NullPointerException.

                  I have done several tests you sujere to solve my problem?

                  follows part of the code.

                   

                   

                      @Produces

                      @Singleton

                      @PerProcessInstance

                      @PerRequest

                      public RuntimeEnvironment produceEnvironment(EntityManagerFactory emf) {

                      KieServices kieServices = KieServices.Factory.get();

                   

                   

                      ReleaseId releaseId = kieServices.newReleaseId( "com.exemple.site", "site-bpm-repo", "1.0.20" );

                      String deploymentId = releaseId.toString();

                      AbstractAuditLogger auditLogger =AuditLoggerFactory.newJPAInstance();

                      ServicesAwareAuditEventBuilder auditEventBuilder = new ServicesAwareAuditEventBuilder();

                      auditEventBuilder.setDeploymentUnitId(deploymentId);

                      auditEventBuilder.setIdentityProvider(new CustomIdentityProvider());

                      auditLogger.setBuilder(auditEventBuilder);

                          RuntimeEnvironment environment = RuntimeEnvironmentBuilder.Factory.get()

                                  .newDefaultBuilder(releaseId)

                                  .entityManagerFactory(emf).

                                  registerableItemsFactory(InjectableRegisterableItemsFactory.getFactory(beanManager, auditLogger)).get();

                   

                   

                          return environment;

                      }

                   

                   

                   

                    @ApplicationScoped

                    public class BPMProcessManagerApiImpl implements BPMProcessManagerApi {

                   

                   

                    @Inject

                    @PerProcessInstance

                    private RuntimeManager singletonManager;

                   

                   

                    @Inject

                    private EntityManagerFactory emf;

                   

                   

                    @PostConstruct

                    private void configure() {

                    singletonManager.toString();

                    RuntimeEngine runtime = singletonManager.getRuntimeEngine(EmptyContext

                    .get());

                   

                   

                    runtime.getKieSession()

                    .getWorkItemManager()

                    .registerWorkItemHandler("Email",

                    new EmailWorkItemHandler());

                    runtime.getKieSession().getWorkItemManager()

                    .registerWorkItemHandler("Rest", new RESTWorkItemHandler());

                    }

                   

                  sorry my English, by google translator.

                   

                  Thank's