1 2 3 Previous Next 39 Replies Latest reply on Dec 22, 2008 8:19 AM by janvandeklok Go to original post
      • 15. Re: Problem with a decision node in a fork,join construct.
        kukeltje

        another thing to try (keep in mind, I do not see them as solutions!!!) is to put a 'lockmode=pessimistic' attribute on the join node.

        • 16. Re: Problem with a decision node in a fork,join construct.
          janvandeklok

          The lockMode = "FORCE". This is what the debugger says.
          I don't know where to look for in the database for the lock mode in the join table???

          the parentToken that will be locked has a node attribute that called Fork !!
          The token that is referred to in the exception has a node reference to the Fork!!.

          I dont know anything about the interal working of JBPM, so I can't say whether this is normal or not??

          Jan

          Will inverstigate your other suggestions tomorrow. I'll keep you posted.


          • 17. Re: Problem with a decision node in a fork,join construct.
            janvandeklok

            The version 3.2.3 has the same (faulty) result. We switched to 3.3.0 in the hope that this problem was fixed in that version. :-((

            Jan

            • 18. Re: Problem with a decision node in a fork,join construct.
              kukeltje

              And it is indeed the parentNode that is locked, so the fork.

              And the default lock is 'FORCE' which is identical to 'UPDATE' (for which 'pessimistic' in jbpm is a synonym.

              UPGRADE_NOWAIT is another oracle specific one, just not sure (and no time to find out) what the exact difference is.

              Btw, could you try to make the transition to the tasknode the first one? It is not realy deterministic, the order in which they are processed, but I'm curious if it makes a difference at all if one of the transitions has gone to a persistent node before the others are processed. The order is my best guess to be able to achieve this

              • 19. Re: Problem with a decision node in a fork,join construct.
                kukeltje

                btw, the join code snippet I saw from you for the join is *not* jbpm 3.3!!! it is older. Or did you copy the small code snippet from the jira issue? If that is the only difference, there is no problem. Othewise please make sure the correct source is used otherwise we might be hunting ghosts.

                • 20. Re: Problem with a decision node in a fork,join construct.
                  mputz

                  I've made another test with a stripped version of your process. I've removed the decision handlers, and made a direct transition from fork to join in one of the branches.

                  This is the result:

                  HSQLDB: 3.2.2: OK, 3.2.3: OK
                  Oracle: 3.2.2: FAILED, 3.2.3: OK
                  Postgres: 3.2.2: FAILED, 3.2.3: OK
                  


                  The session.flush() in org.jbpm.graph.node.Join was introduced in 3.2.3. I'll test this with 3.3.0 later or tomorrow.

                  • 21. Re: Problem with a decision node in a fork,join construct.
                    janvandeklok

                    Ronald,

                    the code snippet came from the source code that was shipped with the 3.3.0 GA release download. I assumed that this is 3.3.0. code!!!

                    Martin,
                    your stripped version exposes the problem correctly I think although such a situation is hypothetical. But I think a fork that transition to a dicision node which in turn transition to the join is a real life business situation the must be supported.

                    It struck me that jbpm is not tested properly with one of the most widely used databases in the world.
                    We also ran into some other problems with the jbpm console and hot process deployment from eclipse when running on a oracle database.
                    We can't start process instances from the console and hot deployment is not possible when using oracle. When running hsqldb these things work ok.

                    But then again HSQLDB is useless for a real business application.


                    I would think that the oracle and mssql database should be the top priority databases to test against!.

                    Is raises the question wether jbpm is the right choice for enterprise software??

                    • 22. Re: Problem with a decision node in a fork,join construct.
                      janvandeklok

                      Ronald,

                      Excuse me, you are right about the code snippet. I pasted the the wrong code in here. This is the correct code:

                      if ( parentToken != null ) {
                      
                       JbpmContext jbpmContext = executionContext.getJbpmContext();
                       Session session = (jbpmContext!=null ? jbpmContext.getSession() : null);
                       if (session!=null) {
                       // force version increment by default (LockMode.FORCE)
                       LockMode lockMode = parentLockMode != null ? LockMode.parse(parentLockMode) : LockMode.FORCE;
                       log.debug("acquiring " + lockMode + " lock on " + parentToken);
                       // lock updates as appropriate, no need to flush here
                      
                       session.flush();
                      
                       session.lock(parentToken, lockMode);
                       }
                      


                      The test I did was with the correct compiled 3.3.0. Join class.

                      • 23. Re: Problem with a decision node in a fork,join construct.
                        kukeltje

                         

                        Is raises the question wether jbpm is the right choice for enterprise software??[/qupte]

                        A valid one (but it is... I can assure you it is used in big companies in very important environments), and I already inquired with 'QA' people about the status of getting access to an oracle database for the QA cycle. The response I got was that they are already working on it. Keep an eye on http://www.jboss.org/community/docs/DOC-12860.

                        We also ran into some other problems with the jbpm console and hot process deployment from eclipse when running on a oracle database.
                        We can't start process instances from the console and hot deployment is not possible when using oracle. When running hsqldb these things work ok.


                        Can you elaborate on this?


                        • 24. Re: Problem with a decision node in a fork,join construct.
                          janvandeklok

                          Ronald,

                          I will post some new treads about the other oracle related problems soon.
                          But the main issue there is (as far as I can see) that the oracle implementation does not auto increment the id fields. Apart from creating a hibernate-sequence, the jbpm (or hibernate) does not seem to use that sequence. We have specified the oracle dialect correctly. I would expect some triggers applied to oracle tables that injects a generated sequence id into the id field when a record is added or some other programmatic logic.

                          the following trigger could simulate the auto-id fields in oracle:


                          CREATE SEQUENCE ACTION_ID_SEQ;
                          create or replace TRIGGER ACTION_ID BEFORE INSERT ON JBPM_ACTION
                           REFERENCING OLD AS old NEW AS new FOR EACH ROW WHEN (NEW.ID_ IS NULL)
                          BEGIN select ACTION_ID_SEQ.nextval into :NEW.ID_ from dual;
                          
                          END;;



                          I went through a lot of documentation, wiki and forum stuff but could not find out how to "activate" the id generation behaviour for an Oracle implemenation.


                          Jan

                          • 25. Re: Problem with a decision node in a fork,join construct.
                            mputz

                            To finish up on my tests from yesterday, removing the flush() in the Join re-introduced the failure on the direct link from fork to join:

                            HSQLDB: 3.2.2: OK, 3.2.3: OK, 3.3.0: OK
                            Oracle: 3.2.2: FAILED, 3.2.3: OK, 3.3.0: FAILED
                            Postgres: 3.2.2: FAILED, 3.2.3: OK, 3.3.0: FAILED
                            


                            Looks like our test suite is not covering this scenario correctly and needs to be enhanced.

                            @Jan, regarding the Oracle sequences, let's follow up on the other thread you've already opened.

                            • 26. Re: Problem with a decision node in a fork,join construct.
                              kukeltje

                              Martin,

                              I did a similar test with 3.3.0 and run it against HSQLDB, H2 and mysql with and without the flush added. They run fine.... strange... can you post your unit test so we are sure we use the same test?

                              • 27. Re: Problem with a decision node in a fork,join construct.
                                mputz

                                if I only had a unit test... sigh... the lack of a proper test is probably the reason why the failure was reintroduced in 3.3.0.

                                I'm pretty convinced this issue only shows on certain dbs, such as Oracle and Postgres. I can give it another try on MySQL, too (and then write a proper test ;-) )

                                • 28. Re: Problem with a decision node in a fork,join construct.
                                  kukeltje

                                  Martin... I found a similarity.... Oracle and Postgress use sequences, mysql, h2 and hsqldb use auto-increment like id's. I've seen that postgress can also support auto-increment if the int8 is changed to 'serial', see http://www.postgresql.org/docs/8.1/interactive/datatype.html#DATATYPE-SERIAL

                                  hibernate does seem to support this: http://opensource.atlassian.com/projects/hibernate/browse/HHH-1675

                                  You have to change 'native' to 'identity' then in the Node.hbm.xml besides changing the sql. Maybe it is worth a try (besides trying with the flush added)

                                  I have a unit test

                                  package org.jbpm.graph.node;
                                  
                                  import org.hibernate.LockMode;
                                  import org.jbpm.db.AbstractDbTestCase;
                                  import org.jbpm.graph.def.ProcessDefinition;
                                  import org.jbpm.graph.exe.ExecutionContext;
                                  import org.jbpm.graph.exe.ProcessInstance;
                                  
                                  public class StaleObjectExceptionJoinTest extends AbstractDbTestCase {
                                  
                                   public void testDirectTransitionsToJoin() {
                                   ProcessDefinition processDefinition = ProcessDefinition
                                   .parseXmlString("<process-definition name='"
                                   + getName()
                                   + "'>"
                                   + " <start-state name='start'>"
                                   + " <transition name='fromStartToFork' to='fork'/>"
                                   + " </start-state>"
                                   + " <fork name='fork'>" // the default
                                   //+ " <fork name='fork' async='true'>" // Async sometimes solves things that should not be a problem
                                   + " <transition name='fromForkToDecide1' to='decide1'/>"
                                   + " <transition name='fromForkToDecide2' to='decide2'/>"
                                   + " <transition name='fromForkToState' to='state'/>"
                                   + " </fork>"
                                   + " <decision name='decide1'>"
                                   + " <handler class='org.jbpm.graph.node.StaleObjectExceptionJoinTest$Decision1'/>"
                                   + " <transition name='fromDecide1ToJoin' to='join'/>"
                                   + " </decision>"
                                   + " <decision name='decide2'>"
                                   + " <handler class='org.jbpm.graph.node.StaleObjectExceptionJoinTest$Decision2'/>"
                                   + " <transition name='fromDecide2ToJoin' to='join'/>"
                                   + " </decision>"
                                   + " <state name='state'>"
                                   + " <transition name='fromStateToJoin' to='join'/>"
                                   + " </state>"
                                   + " <join name='join'>" /* the default */
                                   //+ " <join name='join' lock='"+ LockMode.UPGRADE.toString() + "'>" /* same as 'pessimistic' */
                                   //+ " <join name='join' lock='"+ LockMode.UPGRADE_NOWAIT.toString() + "'>" /* something for Oracle */
                                   //+ " <join name='join' lock='"+ LockMode.READ.toString() + "'>" /*... */
                                   //+ " <join name='join' lock='"+ LockMode.WRITE.toString() + "'>" /*... */
                                   + " <transition name='fromJoinToEnd' to='end'/>"
                                   + " </join>"
                                   + " <end name='end'/>"
                                   + "</process-definition>");
                                  
                                   jbpmContext.deployProcessDefinition(processDefinition);
                                   long processDefinitionId = processDefinition.getId();
                                   newTransaction();
                                  
                                   try {
                                   processDefinition = graphSession
                                   .findLatestProcessDefinition(getName());
                                   ProcessInstance pi = jbpmContext.newProcessInstance(getName());
                                   assertEquals("start", pi.getRootToken().getNode().getName());
                                   pi.signal();
                                   assertEquals("fork", pi.getRootToken().getNode().getName());
                                   assertEquals("join", pi.findToken("/fromForkToDecide1").getNode().getName());
                                   assertEquals("join", pi.findToken("/fromForkToDecide2").getNode().getName());
                                   assertEquals("state", pi.findToken("/fromForkToState").getNode().getName());
                                  
                                   } finally {
                                   newTransaction();
                                   graphSession.deleteProcessDefinition(processDefinitionId);
                                   }
                                  
                                   }
                                  
                                   public static class Decision1 implements DecisionHandler {
                                   private static final long serialVersionUID = 1L;
                                  
                                   public String decide(ExecutionContext executionContext) {
                                   return "fromDecide1ToJoin";
                                   }
                                   }
                                  
                                   public static class Decision2 implements DecisionHandler {
                                   private static final long serialVersionUID = 1L;
                                  
                                   public String decide(ExecutionContext executionContext) {
                                   return "fromDecide2ToJoin";
                                   }
                                   }
                                  
                                  }
                                  
                                  



                                  • 29. Re: Problem with a decision node in a fork,join construct.
                                    kukeltje

                                    H2 is cooooooooooool..... it has an oracle and postgress compatible mode.... If you use it's own H2 driver, but point to a Oracle dialect and state in the connect string the mode is oracle, like:

                                     <!-- hibernate dialect -->
                                    
                                     <property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>
                                    
                                    
                                     <!-- JDBC connection properties (begin) -->
                                     <property name="hibernate.connection.driver_class">org.h2.Driver</property>
                                     <property name="hibernate.connection.url">jdbc:h2:~/jbpm;MVCC=TRUE;MODE=Oracle
                                     </property>
                                     <property name="hibernate.connection.username">sa</property>
                                     <property name="hibernate.connection.password"></property>
                                     <!-- JDBC connection properties (end) -->
                                    
                                    


                                    I get a StaleObjectException..... now is that cool or what.... and even better... it has PostgreSQL, mysql, mssql, derby, mysql, hsqldb compatible modes. PostgreSQL also gives me a SOE!!! wow....

                                    It does not support the dialects fully, but a real large part.... nice....

                                    No more HSQLDB for me...