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

Pete Muir pmuir at redhat.com
Thu May 7 08:18:43 EDT 2009


Marek is going to work on this...

On 6 May 2009, at 15:08, Kevin Conner 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

--
Pete Muir
http://www.seamframework.org
http://in.relation.to/Bloggers/Pete




More information about the seam-dev mailing list