[seam-dev] Seam/jBPM integration within the SOA platform

Dan Allen dan.j.allen at gmail.com
Fri May 8 14:34:34 EDT 2009


I believe that there is an assumption in the Seam jBPM integration that Seam
is going to control transactions for the Hibernate Session used by jBPM.
That is why the following jBPM configuration is required:

    <service name="persistence">
      <factory>
        <bean class="org.jbpm.persistence.db.DbPersistenceServiceFactory">
          <field name="isTransactionEnabled"><false/></field>
        </bean>
      </factory>
    </service>

Of course, then you must have Seam doing all calls to jBPM or else you will
be outside of a transaction. I'm unaware of whether this was considered (not
saying it wasn't). That explains, though, why Seam has the workInTransaction
callbacks.

-Dan

On Wed, May 6, 2009 at 10:08 AM, Kevin Conner <kconner at redhat.com> wrote:

> A few weeks back I was investigating a problem for a customer, related
> to the integration of seam applications within the SOA platform.  I
> managed to chase down the issues but wanted to discuss them further in
> this forum.  Apologies to Pete and Marek for taking so long over this.
>
> First the relevant configuration
>
> Within the SOA platform we have a jBPM/hibernate configuration that
> results in the use of the hibernate JTASessionContext to manage the
> lifecycle of sessions, tying those sessions into the encompassing JTA
> transaction.  We are also using the jBPM JtaDbPersistenceService in
> order to guarantee the existence of a transactional context for the jBPM
> context.
>
> The codebase I have used in this investigation is from the following tag
>
> https://svn.jboss.org/repos/seam/branches/enterprise/JBPAPP_4_3_FP01
>
> When running a seam example on the SOA platform we were seeing an
> exception being thrown as a result of a hibernate session being used
> after it has previously been closed, this was a SessionException with
> the text "Session is closed!".
>
> In chasing this down I discovered two issues
> - an interleaving of the transaction synchronizations between jBPM
>  and hibernate (now removed in jBPM, certainly in 3.2.5-SP5).  This
>  could cause the session to be closed twice, depending on which order
>  the Synchronizations were invoked by the transaction manager.
> - hibernate objects being used outside of a transactional context
>
> It is the latter that I would like to understand further as I was
> surprised to see this given that some areas in the seam/jBPM integration
> explicitly test for the existence of transactions and even create a
> transactional context.  Is there a reason why this is not completely
> done within a transaction?
>
> I appreciate that I am a seam novice and there may be something obvious
> that I am missing.  I do have some suggestions for a fix, however, and
> would like some feedback as to whether they would be appropriate.  I
> have attached the diff file to this message, again based on the previous
> tag.
>
> Thanks in advance for any help that you can give,
>        Kev
>
> --
> JBoss, a Division of Red Hat
> Registered Address: Red Hat UK Ltd, Amberley Place, 107-111 Peascod
> Street, Windsor, Berkshire,
> SI4 1TE, United Kingdom.
> Registered in UK and Wales under Company Registration No. 3798903
> Directors: Michael Cunningham (USA), Charlie Peters (USA), Matt Parsons
> (USA) and Brendan Lane (Ireland)
>
> Index: src/main/org/jboss/seam/bpm/ProcessInstance.java
> ===================================================================
> --- src/main/org/jboss/seam/bpm/ProcessInstance.java    (revision 10421)
> +++ src/main/org/jboss/seam/bpm/ProcessInstance.java    (working copy)
> @@ -36,26 +36,16 @@
>    {
>       if ( !Contexts.isConversationContextActive() ) return null;
>
> -      return new Work<org.jbpm.graph.exe.ProcessInstance>()
> +      Long processId = BusinessProcess.instance().getProcessId();
> +      if (processId!=null)
>       {
> -
> -         @Override
> -         protected org.jbpm.graph.exe.ProcessInstance work() throws
> Exception
> -         {
> -            Long processId = BusinessProcess.instance().getProcessId();
> -            if (processId!=null)
> -            {
> -               //TODO: do we need to cache this??
> -               return
> ManagedJbpmContext.instance().getProcessInstanceForUpdate(processId);
> -            }
> -            else
> -            {
> -               return null;
> -            }
> -         }
> -
> -      }.workInTransaction();
> -
> +         //TODO: do we need to cache this??
> +         return
> ManagedJbpmContext.instance().getProcessInstanceForUpdate(processId);
> +      }
> +      else
> +      {
> +         return null;
> +      }
>    }
>
>    public static org.jbpm.graph.exe.ProcessInstance instance()
> Index: src/main/org/jboss/seam/bpm/ManagedJbpmContext.java
> ===================================================================
> --- src/main/org/jboss/seam/bpm/ManagedJbpmContext.java (revision 10421)
> +++ src/main/org/jboss/seam/bpm/ManagedJbpmContext.java (working copy)
> @@ -83,6 +83,12 @@
>          throw new IllegalStateException("JbpmContext may only be used
> inside a transaction");
>       }
>
> +      if (jbpmContext == null)
> +      {
> +         log.debug( "recreating seam managed jBPM context" );
> +         jbpmContext =
> Jbpm.instance().getJbpmConfiguration().createJbpmContext() ;
> +      }
> +
>       if ( !synchronizationRegistered && !Lifecycle.isDestroying() &&
> transaction.isActive() )
>       {
>          jbpmContext.getSession().isOpen();
> @@ -100,7 +106,7 @@
>
>    public void beforeCompletion()
>    {
> -      log.debug( "flushing seam managed jBPM context" );
> +      log.debug( "closing seam managed jBPM context" );
>       /*org.jbpm.graph.exe.ProcessInstance processInstance =
> ProcessInstance.instance();
>       if (processInstance!=null)
>       {
> @@ -113,47 +119,30 @@
>          //destroyed, flush here:
>          Contexts.getBusinessProcessContext().flush();
>       }
> -      jbpmContext.getSession().flush();
> -      log.debug( "done flushing seam managed jBPM context" );
> +      closeContext();
> +      log.debug( "closed seam managed jBPM context" );
>    }
>
>    public void afterCompletion(int status)
>    {
>       synchronizationRegistered = false;
> -      if ( !Contexts.isEventContextActive() )
> -      {
> -         //in calls to MDBs and remote calls to SBs, the
> -         //transaction doesn't commit until after contexts
> -         //are destroyed, so wait until the transaction
> -         //completes before closing the session
> -         //on the other hand, if we still have an active
> -         //event context, leave it open
> -         closeContext();
> -      }
>    }
>
>    @Destroy
>    public void destroy()
>    {
> -      if ( !synchronizationRegistered )
> -      {
> -         //in requests that come through SeamPhaseListener,
> -         //there can be multiple transactions per request,
> -         //but they are all completed by the time contexts
> -         //are dstroyed
> -         //so wait until the end of the request to close
> -         //the session
> -         //on the other hand, if we are still waiting for
> -         //the transaction to commit, leave it open
> -         closeContext();
> -      }
> +      closeContext();
>    }
>
>    private void closeContext()
>    {
> -      log.debug( "destroying seam managed jBPM context" );
> -      jbpmContext.close();
> -      log.debug( "done destroying seam managed jBPM context" );
> +      if (jbpmContext != null)
> +      {
> +         log.debug( "destroying seam managed jBPM context" );
> +         jbpmContext.close();
> +         log.debug( "done destroying seam managed jBPM context" );
> +         jbpmContext = null;
> +      }
>    }
>
>    public static JbpmContext instance()
> Index: src/main/org/jboss/seam/bpm/TaskInstance.java
> ===================================================================
> --- src/main/org/jboss/seam/bpm/TaskInstance.java       (revision 10421)
> +++ src/main/org/jboss/seam/bpm/TaskInstance.java       (working copy)
> @@ -36,25 +36,16 @@
>    {
>       if ( !Contexts.isConversationContextActive() ) return null;
>
> -      return new Work<org.jbpm.taskmgmt.exe.TaskInstance>()
> +      Long taskId = BusinessProcess.instance().getTaskId();
> +      if (taskId!=null)
>       {
> -
> -         @Override
> -         protected org.jbpm.taskmgmt.exe.TaskInstance work() throws
> Exception
> -         {
> -            Long taskId = BusinessProcess.instance().getTaskId();
> -            if (taskId!=null)
> -            {
> -               //TODO: do we need to cache this??
> -               return
> ManagedJbpmContext.instance().getTaskInstanceForUpdate(taskId);
> -            }
> -            else
> -            {
> -               return null;
> -            }
> -         }
> -
> -      }.workInTransaction();
> +         //TODO: do we need to cache this??
> +         return
> ManagedJbpmContext.instance().getTaskInstanceForUpdate(taskId);
> +      }
> +      else
> +      {
> +         return null;
> +      }
>    }
>
>    public static org.jbpm.taskmgmt.exe.TaskInstance instance()
> Index: src/main/org/jboss/seam/contexts/Contexts.java
> ===================================================================
> --- src/main/org/jboss/seam/contexts/Contexts.java      (revision 10421)
> +++ src/main/org/jboss/seam/contexts/Contexts.java      (working copy)
> @@ -18,6 +18,7 @@
>  import org.jboss.seam.log.LogProvider;
>  import org.jboss.seam.log.Logging;
>  import org.jboss.seam.transaction.Transaction;
> +import org.jboss.seam.util.Work;
>  import org.jboss.seam.web.Session;
>
>  /**
> @@ -344,17 +345,32 @@
>
>             //TODO: it would be nice if BP context spanned redirects along
> with the conversation
>             //      this would also require changes to
> BusinessProcessContext
> -            boolean destroyBusinessProcessContext =
> !Init.instance().isJbpmInstalled() ||
> -                  !BusinessProcess.instance().hasActiveProcess();
> -            if (destroyBusinessProcessContext)
> +            try
>             {
> -               //TODO: note that this occurs from Lifecycle.endRequest(),
> after
> -               //      the Seam-managed txn was committed, but
> Contexts.destroy()
> -               //      calls BusinessProcessContext.getNames(), which hits
> the
> -               //      database!
> -               log.debug("destroying business process context");
> -               destroy( getBusinessProcessContext() );
> +               new Work<Object>()
> +               {
> +                  @Override
> +                  protected Object work() throws Exception
> +                  {
> +                     boolean destroyBusinessProcessContext =
> !Init.instance().isJbpmInstalled() ||
> +                           !BusinessProcess.instance().hasActiveProcess();
> +                     if (destroyBusinessProcessContext)
> +                     {
> +                        //TODO: note that this occurs from
> Lifecycle.endRequest(), after
> +                        //      the Seam-managed txn was committed, but
> Contexts.destroy()
> +                        //      calls BusinessProcessContext.getNames(),
> which hits the
> +                        //      database!
> +                        log.debug("destroying business process context");
> +                        destroy( getBusinessProcessContext() );
> +                     }
> +                     return null;
> +                  }
> +               }.workInTransaction();
>             }
> +            catch (final Exception ex)
> +            {
> +               log.warn("Exception destroying context ", ex);
> +            }
>          }
>
>          if ( !Manager.instance().isLongRunningConversation() )
> Index: build/root.pom.xml
> ===================================================================
> --- build/root.pom.xml  (revision 10421)
> +++ build/root.pom.xml  (working copy)
> @@ -250,7 +250,7 @@
>       <dependency>
>         <groupId>org.jbpm</groupId>
>         <artifactId>jbpm-jpdl</artifactId>
> -        <version>3.2.2.GA_SOA-P</version>
> +        <version>3.2.5.SP5</version>
>       </dependency>
>
>       <dependency>
>
> _______________________________________________
> seam-dev mailing list
> seam-dev at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/seam-dev
>
>


-- 
Dan Allen
Senior Software Engineer, Red Hat | Author of Seam in Action

http://mojavelinux.com
http://mojavelinux.com/seaminaction
http://in.relation.to/Bloggers/Dan

NOTE: While I make a strong effort to keep up with my email on a daily
basis, personal or other work matters can sometimes keep me away
from my email. If you contact me, but don't hear back for more than a week,
it is very likely that I am excessively backlogged or the message was
caught in the spam filters.  Please don't hesitate to resend a message if
you feel that it did not reach my attention.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/seam-dev/attachments/20090508/5f743701/attachment.html 


More information about the seam-dev mailing list