3 Replies Latest reply on Jul 4, 2014 3:43 AM by akoskm

    Threads in WorkItemHandler implementations with Persistence mode enabled

    akoskm

      Hello!

       

      I'm trying to change my existing application to use Persistence mode, following: Chapter 8. Persistence and Transactions

      I have a couple of WorkItemHandler implementations, and most of the important job in these handlers is done in a separate thread.

      This thread is started inside the WorkItemHandler implementation:

       

      class MockHandler implements WorkItemHandler {
      
          @Override
          public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
              new Thread(
                      new MockHandlerAysnc(workItem, manager),
                      "MockHandler"
              ).start();
          }
      
          @Override
          public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
          }
      }
      
      
      class MockHandlerAysnc implements Runnable {
      
          WorkItem item;
          WorkItemManager manager;
      
          MockHandlerAysnc(WorkItem item, WorkItemManager manager) {
              this.item = item;
              this.manager = manager;
          }
      
          @Override
          public void run() {
              // do a lengthy operation
              System.out.println(this.item);
              // then leave the handler
              this.manager.completeWorkItem(this.item.getId(), null);
          }
      }
      
      
      
      
      


      This is worked flawlessly in in-memory mode, but in persistence mode the completeWorkItem line fails with the following error:

       

      WorkItem 19 [name=MockHandler, state=0, processInstanceId=18, parameters{}]
      Exception in thread "MockHandler" java.lang.NullPointerException
        at org.drools.persistence.jpa.JpaPersistenceContext.merge(JpaPersistenceContext.java:111)
        at org.drools.persistence.jpa.processinstance.JPAWorkItemManager.completeWorkItem(JPAWorkItemManager.java:118)
        at org.mycompany.test.jbpm.MockHandlerAysnc.run(WorkItemHandlerWithPersistence.java:143)
        at java.lang.Thread.run(Thread.java:744)
      
      
      
      
      

       

      Do you have any idea why is this happening?

        • 1. Re: Threads in WorkItemHandler implementations with Persistence mode enabled
          akoskm

          Looking at the documentation:

          Chapter 24. Concurrency and asynchronous execution

          my solution to create a separate thread to do the "heavy lifting" and complete the work item from there seems legit, what I'm missing?

          • 2. Re: Threads in WorkItemHandler implementations with Persistence mode enabled
            swiderski.maciej

            best is to actually pass the runtime manager to your background thread instead of work item manager that will be deactivated after transaction completes. So ensure you will have runtime manager in your work item handler and then pass it into the thread so when the job is done you can get RuntimeEngine out of it and then ksession and finally work item manager to complete the work.

             

            Take a look at jbpm executor as well that provides all the async features you most likely need without any additional coding.

             

            HTH

            1 of 1 people found this helpful
            • 3. Re: Re: Threads in WorkItemHandler implementations with Persistence mode enabled
              akoskm

              Thanks for your answer.

               

              This was actually my error. I have a couple of unit tests for my jBPM persistence modules.

              I figured out that after starting the process in the unit test, my handler actually starts to work asynchronously, but the unit test finishes before the handler is completed.

              This of course shuts down the main thread which was started by the unit test itself:

               

                  @Test
                  public void humanTaskTest() throws Exception {
                      RuntimeManager manager = getRuntimeManager("process/humantask/HumanTask.bpmn");
                      RuntimeEngine runtime = manager.getRuntimeEngine(EmptyContext.get());
                      KieSession ksession = runtime.getKieSession();
              
                      ProcessInstance proc = ksession.startProcess("com.sample.humantask", null); // <-- handler is invoked and started the background thread but the unit test exits after this line
                  }
              
              
              

              I've achieved the correct behavior by putting a Thread.sleep(20000) after startProcess.

              My async handler had enough time to finish its job and everything worked as expected.