4 Replies Latest reply on Sep 11, 2009 2:14 PM by Michael Sorg

    jBPM 4 and thread-safeness

    Michael Sorg Newbie

      Hi,

      I've been working for 2-3 years with jBPM 2/3 and now have the time to evaluate if I should switch to version 4 in future. In the user-guide I read the following:


      For all objects that are referenced by a class name, will be instantiated during parsing time. Which implies that the objects have to be threadsafe. This is typically OK since those objects are typically immutable

      In jBPM 3 an ActionHandler-Implementation was instantiated (lazy) at runtime. There was no need for an Action-impl to be threadsafe (and if several config-arguments were injected via processdefinition it wasn't for sure threadsafe :-). But although it was not threadsafe it was reusable - if an action was executed a second time (not concurrently) it was already instantiated.

      But what is the difference in jBPM4 now? In a Java-Task for example it is still possible to provide arguments via declaration so this object (which is referenced by class-name) will never be threadsafe (except I chose the dirty way and make the variables final).

      So my questions are:

      Why do these objects have to be threadsafe? For me it doesn't make a difference if such a class is instantiated at parsing- or runtime.
      If they must be threadsafe why are the classes in the examples not threadsafe
      Why are objects instantiated (at parsing time) which maybe never will be used (who can guess the path of execution)?

      Thanks in advance

      regards,

      Michael

        • 1. Re: jBPM 4 and thread-safeness
          Ronald van Kuijk Master

          Wrong forum... Wow... never thought I would say that in the user forum... hahaha... good questions but more something for the dev forum. I'm not into the low level details of this so I'll ask others to respond.

          (already did)

          • 2. Re: jBPM 4 and thread-safeness
            Tom Baeyens Master

            good question/remark.

            event listeners threadsafety in jbpm has a different meaning then threadsafe in general java. so therefor, we should indeed update the docs and not use the word threadsafe for it.

            in strickt java sense, nutable methods on threadsafe objects should be synchronized. in jbpm sense, the only requirement is that you don't change your member fields in the execute method. setters of event handlers don't have to be synchronized as this is done during initialization before jbpm will use the object.

            in jbpm 3, a new delegation object was instantiated *for every usage* of an action (event listener). in jbpm 4, we want to get to a situation that the event listener object becomes a part of the process definition object graph. and hence it gets cached and used by all threads.

            hth

            • 3. Re: jBPM 4 and thread-safeness
              Ronald van Kuijk Master

              Now THIS is what I call support...

              and I think (!) it is true for actionhandlers as well and decisionhandlers and ....

              • 4. Re: jBPM 4 and thread-safeness
                Michael Sorg Newbie

                First of all thanks for the fast response :-)

                If this is the wrong forum for this kind of question could you please move the thread to the dev-forum? ...because I still have some questions concerning this issue.


                in strickt java sense, nutable methods on threadsafe objects should be synchronized. in jbpm sense, the only requirement is that you don't change your member fields in the execute method.

                I totally agree to that approach. It's the same as the singleton-model in spring. The threadsafeness (even more: reintrance) is guaranteed if the developer observes some basic rules. If he does not strange things may occur.


                in jbpm 4, we want to get to a situation that the event listener object becomes a part of the process definition object graph. and hence it gets cached and used by all threads

                How can you handle this? IMHO this strategy only can work if the member variables of a handler-impl are set with constant values. Since it is possible to inject dynamic values in a member-var (e.g. return values from a prior method-call) it will have the same effect than changing the member fields in the handler-class itself.

                For better explanation of what I mean a short piece of code (sorry it is JBPM 3-style but I am atm still a rookie in JBPM 4 :-( )

                // in class A I create a ProcessDefinition
                ProcessDefinition pd = new ProcessDefinition(...);
                
                // now I start a couple of instances of class B (which extend Thread)
                // and start the threads
                for(int i = 0; i < 100; i++) {
                 new B(pd).start();
                }
                
                // class B looks something like that:
                public class B extends Thread {
                
                 private ProcessDefinition pd;
                
                 public B(ProcessDefinition pd) {
                 this.pd = pd;
                 }
                
                 public void run() {
                 //Note that I start the ProcessInstance depending on the same ProcessDefinition-instance
                 ProcessInstance pi = new ProcessInstance(this.pd);
                 pi.signal();
                 }
                }
                

                In JBPM 3 an action-delegate was instantiated at first access. After that the already instantiated object was used:
                // snippet from Delegation
                public Object getInstance() {
                 if (instance==null) {
                 instance = instantiate();
                 }
                 return instance;
                 }
                

                So if I understood you right the behaviour must be the same than in JBPM 4 after the point of the instantiation of the delegate.

                This code produces the result I explained before:

                If the member-fields of the used handlers are only set with constant values everything works fine
                If the member-fields are set dynamically (e.g. via expressions) it becomes broken

                And now the big question:

                Have I understood something wrong or is this kind of test-scenario (multiple threads using the same ProcessDefinition-instance for instantiating ProcessDefinitions a kind of operation outside the specification?