13 Replies Latest reply on Jun 28, 2007 2:06 PM by estaub

    jBPM and Message Driven Beans

    new4jboss

      Hi all,
      I'm facing jBPM for the first time and just when i was about to start coding my application i faced an issue that i couldn't find any answer in the last two days.

      I'm using jBPM-3.1.3 as lib's (jbpm-3.1.3.jar and jbpm-identity-3.1.3.jar) inside my Enterprise Application (.ear) deployed in a SJSAS 8.1 2005Q1.
      For the database I'm using Oracle 9i with the Oracle JDBC driver, 9.2.0.8 version. Hibernate connects through a datasource defined in the SJSAS.

      Here is my scenario:

      processdefinition.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <process-definition xmlns="" name="suspension.par">
       <start-state name="start">
       <transition name="" to="node1"></transition>
       </start-state>
       <node name="node1">
       <action class="my.package.SendRequest"/>
       <transition name="" to="state1"></transition>
       </node>
       <state name="state1">
       <transition name="" to="end1"></transition>
       </state>
       <end-state name="end1"></end-state>
      </process-definition>
      


      I have a jsp that creates a new ProcessInstance:
      JbpmContext jbpmContext = JbpmConfiguration.getInstance().getCurrentJbpmContext();
      //creates a new process instance
      ProcessInstance processInstance = jbpmContext.newProcessInstance("suspension.par");
      jbpmContext.save(processInstance);
      //starts the workflow
      processInstance.signal();
      


      As this point the workflow instance has received a signal to move forward to "node1" where it calls the my.package.SendRequest. This ActionHandler sends a request to a Message Driven Bean (MDB) through a queue.

      Thats where the problem reveals itself, and lets see if I can explain here what is happening.

      Since the creation of the process instance was responsibility of the jsp, so lets assume that the signal sent inside this jsp makes the MDB receiving the request before the jsp call to jbpmContext.close().

      From what i understood the database "writing" occurs when we call jbpmContext.close(), so nothing was written to the database as for the time of MDB receiving the request.

      In the request that the MDB is receiving is the processInstanceId that is used to load the ProcessInstance from the database. But when i try to do that:
      org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [org.jbpm.graph.exe.ProcessInstance#644]
       at org.hibernate.impl.SessionFactoryImpl$1.handleEntityNotFound(SessionFactoryImpl.java:375)
       at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:79)
       at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:68)
       at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:111)
       at org.hibernate.proxy.pojo.cglib.CGLIBLazyInitializer.invoke(CGLIBLazyInitializer.java:140)
       at org.jbpm.graph.exe.ProcessInstance$$EnhancerByCGLIB$$f514ef34.signal(<generated>)
       at my.package.ResponseMDBean.onMessage(ResponseMDBean.java:88)
       at sun.reflect.GeneratedMethodAccessor107.invoke(Unknown Source)
       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
       at java.lang.reflect.Method.invoke(Method.java:585)
       at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:983)
       at com.sun.enterprise.security.SecurityUtil.invoke(SecurityUtil.java:147)
       at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:956)
       at com.sun.ejb.containers.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:42)
       at com.sun.enterprise.connectors.inflow.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:130)
       at $Proxy25.onMessage(Unknown Source)
       at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:187)
       at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:45)
       at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(Unknown Source)
      



      Can anyone help me on this please?
      Thanks in advance,
      Délio Guerra

        • 1. Re: jBPM and Message Driven Beans

          When you look at the database "by hand" using DBVisualizer or whatever, what do you see? Is the ProcessInstance really being persisted at all?

          -Ed Staub

          • 2. Re: jBPM and Message Driven Beans
            new4jboss

            Yes ProcessInstance is being persisted, the exception only happens now and then when the MDB starts the process before the jsp commits the transaction. When the MDB processes the request after the jsp closes the jbpmContext, it works fine.

             SELECT JBPM_PROCESSINSTANCE.ID_,
             JBPM_PROCESSINSTANCE.START_,
             JBPM_PROCESSINSTANCE.END_,
             JBPM_PROCESSINSTANCE.ROOTTOKEN_,
             JBPM_NODE.NAME_
             FROM JBPM_PROCESSINSTANCE,
             JBPM_TOKEN,
             JBPM_NODE
             WHERE JBPM_PROCESSINSTANCE.ROOTTOKEN_ = JBPM_TOKEN.ID_
             AND JBPM_TOKEN.NODE_ = JBPM_NODE.ID_
            ORDER BY JBPM_PROCESSINSTANCE.START_
            
            output:
            
             ID_ START_ END_ ROOTTOKEN_ NAME_
             ------ ----------------------- ----------------------- ------------- --------
             696 2007-01-29 20:34:51.532 2007-01-29 20:34:57.003 697 end1
             700 2007-01-29 20:34:52.704 2007-01-29 20:34:58.772 701 end1
             704 2007-01-29 20:34:57.976 (null) 705 state1
             708 2007-01-29 20:34:58.551 2007-01-29 20:35:00.627 709 end1
            
            


            Thanks,
            Délio Guerra

            • 3. Re: jBPM and Message Driven Beans
              kukeltje

              Yes, you kind of answered your own question... you do not do a close() so nothing is written to the DB (might not even happen then if you use CMT)

              So the MDB cannot retrieve the processinstances.... ???? or do I miss something???

              • 4. Re: jBPM and Message Driven Beans
                new4jboss

                How should I configure hibernate.cfg.xml to use CMT with SJSAS 8.1 2005Q1?
                I saw some configurations with:

                <hibernate-configuration>
                 <session-factory name="jBpmSessionFactory">
                
                 <!-- jdbc connection properties -->
                 <property name="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</property>
                 <property name="hibernate.connection.datasource">jdbc/jBpmDS</property>
                
                 <!-- other hibernate properties
                 <property name="hibernate.format_sql">true</property>
                 <property name="hibernate.use_sql_comments">true</property>
                 -->
                 <property name="hibernate.show_sql">false</property>
                 <property name="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</property>
                
                 <property name="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory</property>
                 <property name="transaction.manager_lookup_class">????????????</property>
                
                 .
                 .
                 .
                
                 </session-factory>
                </hibernate-configuration>
                


                I couldn't find any SJSAS transaction.manager_lookup_class.
                I'm using the org.jbpm.web.JbpmContextFilter to create the jbpmContext, must I close the jbpmContext inside the jsp? if so, the code (inside jsp) will look something like:
                JbpmContext jbpmContext = JbpmConfiguration.getInstance().getCurrentJbpmContext();
                //creates a new process instance
                ProcessInstance processInstance = jbpmContext.newProcessInstance("suspension.par");
                jbpmContext.save(processInstance);
                jbpmContext.close();
                //starts the workflow
                processInstance.signal();
                


                Can I call processInstance.signal() after closing the jbpmContext????

                Thanks once again,
                Délio Guerra

                • 5. Re: jBPM and Message Driven Beans
                  new4jboss

                  Hi all,
                  I did what I didn't want, but works.
                  I removed the org.jbpm.web.JbpmContextFilter filter configuration from web.xml and made the following in index.jsp:

                  JbpmContext jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
                  long processInstanceId = 0L;
                  
                  try {
                   ProcessInstance processInstance = jbpmContext.newProcessInstance("suspension.par");
                   processInstanceId = processInstance.getId();
                   jbpmContext.save(processInstance);
                  
                  } finally
                  {
                   jbpmContext.close();
                  }
                  
                  jbpmContext = JbpmConfiguration.getInstance().createJbpmContext();
                  
                  try {
                   ProcessInstance processInstance = jbpmContext.loadProcessInstance(processInstanceId);
                   processInstance.signal();
                  } finally
                  {
                   jbpmContext.close();
                  }
                  


                  As you can see, this is not very pretty, but works.

                  Does anyone know a better way to guarantee that the ProcessInstance is persisted before we signal it?
                  I would appreciate a solution that delegates this responsibility to the container (CMT).

                  Thanks,
                  Délio Guerra


                  • 6. Re: jBPM and Message Driven Beans

                    Would inserting a timer of 0 duration do the trick?
                    It's ugly, too, of course.

                    I'm wondering if this problem is peculiar to process creation, or if a similar race condition can happen later on an update as well. Hopefully, a row-lock in the database prevents undesired concurrency - but I don't know whether that's actually done, and which databases it works on. Does anyone know?

                    -Ed Staub

                    • 7. Re: jBPM and Message Driven Beans
                      gforam

                      I have the same problem and i am using process-state to call sub workflow. So I dont have a solution at all.

                      • 8. Re: jBPM and Message Driven Beans

                        Oops, my bad... Tom Baeyens addressed these problems in update (process-already-exists) scenarios in this thread:
                        http://www.jboss.com/index.html?module=bb&op=viewtopic&t=76751
                        This doesn't help @new4jboss, of course, because the process isn't created yet (sometimes!).
                        -Ed Staub

                        • 9. Re: jBPM and Message Driven Beans
                          gforam

                          This still does not solve my problem. I have a process which spawns a sub-process instance using process-state.
                          This process-instance is queueing up a message and once the message finishes its processing, it tries to signal the token to resume. however, at that point, i get an exception saying "No row with the given identifier exists: [org.jbpm.graph.exe.ProcessInstance#489]"
                          I am trying to load the process instance based on the id.
                          The problem is the process instance is not saved to the database. How do i make it save to the database?

                          • 10. Re: jBPM and Message Driven Beans

                            @gforam,

                            For now, if I were you I'd try @new4jboss's save-and-reload hack.
                            You haven't already, right?

                            I think I've managed to raise a little concern about this problem at jboss.com - the timing-dependent nature makes it a real support headache that they shouldn't want. Stay tuned...

                            -Ed Staub
                            (newbie)

                            • 11. Re: jBPM and Message Driven Beans
                              gforam

                              I am using version 3.0.2. The solution suggested by new4jboss does not work since there is a change of api with the new version.
                              Is there a solution for version 3.0.2?

                              • 12. Re: jBPM and Message Driven Beans
                                gforam

                                Also since i am calling the sub-process using the process-state, i dont have the session that created the process instance or the context that created the process instance.

                                • 13. Re: jBPM and Message Driven Beans

                                  In case anyone has this problem again and is searching the forum for clues... see http://jira.jboss.com/jira/browse/JBPM-983