6 Replies Latest reply on Dec 28, 2009 7:38 AM by ajaygautam

    Java instance being reused across workflows.

      Problem:

      Java instance from one workflow is being re-used in the next workflow (jbpm 4.2)!

       

      Background:

      My workflow has a java task:

         <java class="com.....CheckTradeAttribute" name="Check Amendment type"

               method="compareTradeAttribute"

               var="ecomonicAmmedResult">

            // .....
            <field name="request"><object expr="#{wfRequest}"/></field>

            // .....


            <transition to="where to go"/>
         </java>

       

      The java class looks like:

      public class CheckTradeAttribute {
          private static final Logger logger = Logger.getLogger(CheckTradeAttribute.class);


          // ......

          private WorkflowEngineRequest request;


          public String compareTradeAttribute() {

                  // ....

                  logger.debug("Input request: " + request);
                  logger.debug("I am: " + toString());

                  // .....
          }
          // ....

      }

       

      My first unit test: Starts a new workflow, reaches this task, assigns the appropriate value from #{request} to request member.

      Test finishes, the workflow is closed, all is well

       

      Second unit test starts, starts a new workflow, reaches this task.

       

      Now, the test *should* create a new instance of the class, and assign the appropriate value from #{request} to request.

      But what *actually* happens is that the old instance (from the previous unit test) is used again! - and it contains the old values!

       

      Any way to tell jbpm to create a new instance for the new workflow?

       

      Any help / pointers would be greatly appreciated.

       

      Thanks

       

      Ajay

        • 1. Re: Java instance being reused across workflows.

          Might be worth mentioning that I tried to reproduce the error with JBPM examples, but was UNABLE to do so...


          Complete updated files attached (if you want to resun the test and see that it works fine for examples). Here are my changes:

          package org.jbpm.examples.java

           

          // ...

           

          public class JavaInstantiateTest extends JbpmTestCase {

          // ...

           

            public void testJavaInstantiateFine() {
              final Map<String, Object> variables = new HashMap<String, Object>();
              variables.put("hand", new Hand());
              variables.put("joesmoe", new JoeSmoe());
              variables.put("newState", "fine");

              final ProcessInstance processInstance = executionService.startProcessInstanceByKey("Java", variables);
              final String pid = processInstance.getId();

              final String answer = (String) executionService.getVariable(pid, "answer");
              assertEquals("I'm fine, thank you.", answer);

              final Hand hand = (Hand) executionService.getVariable(pid, "hand");
              assertTrue(hand.isShaken());
            }

            public void testJavaInstantiateSmooth() {
              final Map<String, Object> variables = new HashMap<String, Object>();
              variables.put("hand", new Hand());
              variables.put("joesmoe", new JoeSmoe());
              variables.put("newState", "Smooth");

              final ProcessInstance processInstance = executionService.startProcessInstanceByKey("Java", variables);
              final String pid = processInstance.getId();

              final String answer = (String) executionService.getVariable(pid, "answer");
              assertEquals("I'm Smooth, thank you.", answer);

              final Hand hand = (Hand) executionService.getVariable(pid, "hand");
              assertTrue(hand.isShaken());
            }
          }

           

          Update to jbpm java task:

            <java name="greet"
                  class="org.jbpm.examples.java.JohnDoe"
                  method="hello"
                  var="answer"
                  g="96,16,83,52">
                 
              <field name="state"><object expr="#{newState}"/></field>
              <arg><string value="Hi, how are you?"/></arg>
             
              <transition to="shake hand" />
            </java>

           

          This works as it should!

           

          So... I think I am doing a stupid mistake somewhere, but can't really put my finger on it.

           

          Any help / pointers in the right direction would be appreciated.

           

          Thanks

           

          Ajay Gautam

          • 2. Re: Java instance being reused across workflows.

            Changing the debug level from DEBUG to TRACE reveals that the code tries to create a ReporitoryCache.

             

            2009-12-21 13:49:19,743 DEBUG Log4jLog     - executing activity(Check Amendment Type)
            2009-12-21 13:49:19,743 TRACE Log4jLog     - org.jbpm.pvm.internal.repository.RepositoryCache not found in transaction 26358318
            2009-12-21 13:49:19,743 TRACE Log4jLog     - found org.jbpm.pvm.internal.repository.RepositoryCache in process-engine
            2009-12-21 13:49:19,743 TRACE Log4jLog     - delivering org.jbpm.pvm.internal.repository.RepositoryCacheImpl
            2009-12-21 13:49:19,759 DEBUG CheckTradeAttribute     - Constructing CheckTradeAttribute. I am com.rbs.gbm.rates.workflowengine.engine.CheckTradeAttribute@14af469
            ...

            ...

            2009-12-21 13:49:20,165 DEBUG Log4jLog     - executing activity(Check Amendment Type)
            2009-12-21 13:49:20,165 TRACE Log4jLog     - creating null
            2009-12-21 13:49:20,165 TRACE Log4jLog     - searching for method compareTradeAttribute in com.rbs.gbm.rates.workflowengine.engine.CheckTradeAttribute
            2009-12-21 13:49:20,165 TRACE Log4jLog     - found matching method com.rbs.gbm.rates.workflowengine.engine.CheckTradeAttribute.compareTradeAttribute

             

            For the first unit test, the cache is created, and populated with a new object. For the 2nd unit test, the same object is retrieved from the cache!

             

            Any way to change the behavior to create new object every time?

             

            Ajay

            • 3. Re: Java instance being reused across workflows.
              kukeltje

              Afaik, you need to assume statelessness in the automatic java activities, just like with stateless sessionbeans. The difference between your example and the testcase is the visability of the member field (private vs package ('default')). Try changing that

               

              Cheers,

               

              Ronald

              • 4. Re: Java instance being reused across workflows.
                What I found is that if I have members in the object, its cached, but if I remove all members, and pass all data using parameters, then the instance is not cached. I converted the calls to params, and its working fine now.
                • 5. Re: Java instance being reused across workflows.
                  jbarrez

                  As Ronald states, automatic activitites should't have state. So if you want to inject runtime data, you'll have to pass them by parameter.

                   

                  This is also described in the user guide:


                  "For all objects that are referenced by a class name, will be         instantiated during parsing time.  Which implies that the objects aren't       allowed to store non-stateless data"

                  • 6. Re: Java instance being reused across workflows.

                    Thanks for pointing that out Joram.

                    Must have overlooked it.

                     

                    Happy new year.