• Seam jBPM integration


     

    Seam provides two nice additions to JBPM the first one (which this tutorial is about) is a powerful integration between Seam components + JSF and JBPM, the second one is Page Flow Definition : we'll treat this latter in a separate tutorial as it's simply a different way to describe your application flow and what actions and decisions can happen in each place.

    How seam integrates with JBPM ?

    Seam folds business processes into the Seam container by relying on three key coordinators:

    • The business process context: Seam assimilates the stateful context bound to the process instance as one of its own. Business process-scoped context variables are exchanged with the jBPM process context transparently, but are otherwise treated just like any other context variable. They can participate in bijection and be resolved using EL notation. Value expressions can also be used in the process definition descriptor to resolve context variables in the Seam container.
    • Declarative business process controls: A set of annotations and page descriptor tags are included that can initiate or resume a process instance, start and end tasks, and bring variables from an active process into scope, all without calling out directly to jBPM. Seam as includes a set of UI controls for selecting the process or task instance on which to operate.
    • Identity management: Seam provides a basic component named actor for registering the actor id and group ids that will be passed on to the process instance to record the current participant. The actor component is typically populated during the authentication routine.

    Configuring Seam to work with JBPM

    Step 1 : Add JBPM libraries

    The JAR file jbpm-3.X.X.jar is required for jBPM and it is located under the lib directory of the Seam distribution. We need to place this JAR file at the root of the EAR and then add a reference to the JAR in the application.xml file.
    Here's a sample of your application.xml file with JBPM libs in it

    1. <application>  
    2. <display-name>Sample JBPM Seam Application</display-name>  
    3. <module>  
    4.  <web>  
    5.   <web-uri>seamJbpm.war</web-uri>  
    6.    <context-root>/seamJbpm</context-root>  
    7.  </web>  
    8. </module>  
    9. <module>  
    10.  <java>jboss-seam.jar</java>  
    11. </module>  
    12. <module>  
    13.  <java>jbpm-3.1.2.jar</java>  
    14. </module>  
    15. </application>  

    Step 2: Add hibernate config file

    As we saw in our previous tutorial, jBPM works by interacting with a database, and it uses Hibernate as its persistence mechanism for the database. You can pickup the hibernate.cfg.xml file that comes with the jBPM release. This file needs to be inserted into the root of your ear.

    Step 3: Tell seam which are your process definitions (and pageflows)

    In your components.xml you need to declare the process definitions used by your applications

    1. <bpm:jbpm>  
    2.         <bpm:process-definitions>  
    3.          <value>processDefinition.xml</value>  
    4.         </bpm:process-definitions>  
    5.     </bpm:jbpm>  

    (Besides this you must declare here you pageflows, but we'll explore Page Flows in the next tutorial)


    Step 4: Let Seam manage transactions

    JBPM used in a standalone environment uses its own resource-local transactions when performing persistence operations. However when used in combination with Seam this can lead to transaction conflicts: so you need simply tell JBPM to participate in the global transaction managed by Seam (and not use its own)

    Add this line to jbpm.cfg.xml file:

    1. <jbpm-configuration>  
    2.   <jbpm-context>  
    3.     <service name="persistence">  
    4.        <factory>  
    5.           <bean class="org.jbpm.persistence.db.DbPersistenceServiceFactory">  
    6.              <field name="isTransactionEnabled"><false/></field>  
    7.           </bean>  
    8.        </factory>  
    9.     </service>  
    10.     <service name="tx" factory="org.jbpm.tx.TxServiceFactory" />  
    11.     <service name="message" factory="org.jbpm.msg.db.DbMessageServiceFactory" />  
    12.     <service name="scheduler" factory="org.jbpm.scheduler.db.DbSchedulerServiceFactory" />  
    13.     <service name="logging" factory="org.jbpm.logging.db.DbLoggingServiceFactory" />  
    14.    <service name="authentication" factory="org.jbpm.security.authentication.DefaultAuthenticationServiceFactory" />  
    15.   </jbpm-context>  
    16. </jbpm-configuration>  

    (Also this file will stay in the root of the ear)

    A Sample application


    Piece 1: the processdefinition
     
    Here we'll show a simple process which has 2 Tasks in it. 
    An order is placed at the beggining of the process and then the order needs to be delivered. Just to keep it simple we have only one actor in this process which will be the used logged in.

    jbpm seam integration 
    Picture 1: the process view designed with Eclipse plugin

    1. <process-definition xmlns="urn:jbpm.org:jpdl-3.2" name="simple">  
    2.  <start-state name="start">  
    3.   <transition name="trPlaceOrder" to="PlaceOrder" />  
    4.  </start-state>  
    5.  <task-node name="PlaceOrder">  
    6.   <task name="placeOrderTask">  
    7.    <assignment actor-id="#{actor.id}" />  
    8.   </task>  
    9.   <transition name="next" to="Deliver" />  
    10.   <transition name="cancel" to="error" />  
    11.  </task-node>  
    12.  <task-node name="Deliver">  
    13.   <task name="getFromStock">  
    14.    <assignment actor-id="#{actor.id}" />  
    15.   </task>  
    16.   <transition name="next" to="end" />  
    17.   <transition name="cancel" to="error" />  
    18.  </task-node>  
    19.  <end-state name="error" />  
    20.  <end-state name="end" />  
    21. </process-definition>  

    Notice the expression #{actor.id}. This is an example of how to inject a seam component into your process definition. In the next module everything will be clear.

     


    Piece 2: the login module & login view:
    The login module and the login view are showed here :
    This is the login view:

    1. <%@ taglib uri="<a href="http://java.sun.com/jsf/html">http://java.sun.com/jsf/html</a>prefix="h"%>  
    2. <%@ taglib uri="<a href="http://java.sun.com/jsf/core">http://java.sun.com/jsf/core</a>prefix="f"%>  
    3. <html>  
    4. <head>  
    5. <title>Login</title>  
    6. </head>  
    7. <body>  
    8. Enter your username  
    9. <f:view>  
    10.  <h:form>  
    11.    <div>  
    12.      <h:inputText value="#{login.user}"/>  
    13.      <h:commandButton value="Login" action="#{login.login}"/>  
    14.    </div>  
    15.  </h:form>  
    16. </f:view>  
    17. </body>  
    18. </html>  

    This is the login Module

    1. import org.jboss.seam.annotations.In;  
    2. import org.jboss.seam.annotations.Name;  
    3. import org.jboss.seam.bpm.Actor;  
    4.   
    5. @Name("login")  
    6. public class LoginModule  
    7. {  
    8.      
    9.    @In private Actor actor;  
    10.      
    11.    private String user;  
    12.   
    13.    public String getUser() {  
    14.       return user;  
    15.    }  
    16.   
    17.    public void setUser(String user) {  
    18.       this.user = user;  
    19.    }  
    20.      
    21.    public String login()  
    22.    {  
    23.       actor.setId(user);  
    24.       return "/todo.jsp";  
    25.    }  
    26. }  

    Here's the actor object we've seen before.

    jbpm seamWhat is the Actor ?  it's a Seam component that is stored in the session. In general, you should create your actor component when you are logging in to the website.

    :







    The actor will be used later on to assign the Task to an actor-id:

    <task name="getFromStock">
        <assignment actor-id="#{actor.id}"/>
    </task>


    Piece n. 3 : the POJO process manager.

    Believe it or not this little POJO does all the job that is needed to Create a task, and handle @Start and @Stop

    1. import org.jboss.seam.annotations.bpm.CreateProcess;  
    2. import org.jboss.seam.annotations.bpm.EndTask;  
    3. import org.jboss.seam.annotations.Name;  
    4. import org.jboss.seam.annotations.bpm.StartTask;  
    5. import org.jboss.seam.annotations.*;  
    6. import org.jboss.seam.ScopeType;  
    7.   
    8. @Name("orderStock")  
    9.   
    10.    
    11. public class OrderStock   
    12. {  
    13.    
    14.    @Out(scope=ScopeType.BUSINESS_PROCESS, required=false)  
    15.    Long processQuantity;  
    16.      
    17.    private int quantity ;  
    18.        
    19.    public int getQuantity()  
    20.    {  
    21.       return quantity;  
    22.    }  
    23.   
    24.    public void setQuantity(int quantity) {  
    25.       this.quantity = quantity;  
    26.    }  
    27.        
    28.   @CreateProcess(definition="simple")  
    29.   public  void startProcess() {        
    30.     processQuantity = new Long(getQuantity());  
    31.   }  
    32.   @StartTask  
    33.   @EndTask(transition="next")  
    34.     public void done() {  
    35.   }  
    36.   @StartTask  
    37.   @EndTask(transition="cancel")  
    38.     public void cancel() {  
    39.   }  
    40.      
    41. }  


    It's most intuitive: the method startProcess will be recalled by JSF to start the JBPM process

       @CreateProcess(definition="simple")
       public void startProcess() {
       .....
       }
      
    You see, process definition is passed as parameter to the annotation. The Seam @StartTask annotation starts work on a task. The @EndTask ends the task, and allows the business process execution to resume.
    In this sample we've two methods done and cancel which will be used to drive our process : calling done moves the Token to the transition "next" while calling cancel moves to the transition "cancel". (Here for keeping it simple the methods handle both @StartTask and @EndTask but you're free to use a separate method for each of this phases)

    A last thing: maybe you've noticed the expression:
    @Out(scope=ScopeType.BUSINESS_PROCESS, required=false)
    Long processQuantity;

    this outjects the process variable processQuantity and makes it available to the view.

    Piece n. 4 : the view component

    Ok so we need a last piece of this puzzle: the view component. this will be a standard JSF page BUT....with special Seam annotations in it:

    1. <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>  
    2. <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>  
    3. <%@ taglib uri="http://jboss.com/products/seam/taglib" prefix="s"%>  
    4. <html>  
    5. <body>  
    6. <h2>Order system</h2>  
    7. <f:view>  
    8.    <h:form id="list">  
    9.       <div>  
    10.          <h:outputText value="There are no order at the moment." rendered="#{empty taskInstancePriorityList}"/>  
    11.          <h:dataTable value="#{taskInstancePriorityList}"   
    12.             var="task" rendered="#{not empty taskInstancePriorityList}"  
    13.             bgcolor="#F1F1F1" border="10">  
    14.             <h:column>  
    15.                 <f:facet name="header">  
    16.                     <h:outputText value="Created"/>  
    17.                 </f:facet>  
    18.                 <h:outputText value="#{task.taskMgmtInstance.processInstance.start}">  
    19.                     <s:convertDateTime type="date"/>  
    20.                 </h:outputText>  
    21.             </h:column>  
    22.               
    23.             <h:column>  
    24.                 <f:facet name="header">  
    25.                     <h:outputText value="Name"/>  
    26.                 </f:facet>  
    27.                   <h:outputText value="#{task.name}"/>  
    28.             </h:column>  
    29.               
    30.             <h:column>  
    31.                 <f:facet name="header">  
    32.                     <h:outputText value="Quantity"/>  
    33.                 </f:facet>  
    34.                   <h:outputText value="#{task.variables['processQuantity']}"/>  
    35.             </h:column>  
    36.   
    37.             <h:column>  
    38.                 <s:button action="#{orderStock.done}" taskInstance="#{task}" value="Done"/>  
    39.             </h:column>  
    40.             <h:column>  
    41.                 <s:button action="#{orderStock.cancel}" taskInstance="#{task}" value="Cancel"/>  
    42.             </h:column>  
    43.   
    44.          </h:dataTable>  
    45.       </div>  
    46.       <div>  
    47.       <h:messages/>  
    48.       </div>  
    49.    </h:form>  
    50.    <h:form id="new">  
    51.       <div>  
    52.          <h:inputText value="#{orderStock.quantity}" />  
    53.          <h:commandButton value="Enter order quantity" action="#{orderStock.startProcess}"/>  
    54.       </div>  
    55.    </h:form>  
    56. </f:view>  
    57. </body>  
    58. </html>  

    Here's a little explanation to the expression you find in the JSF:

    #{taskInstancePriorityList}  Loads the Datatable with an array of Tasks
    #{task.taskMgmtInstance.processInstance.start}  Displays the start date of the process
    #{task.name}  recalls task.getName()
    #{task.variables['processQuantity']} Displays the task variable processQuantity
    #{task} the reference to the TaskInstance

    #{orderStock.done} Simple invocation of method done
    #{orderStock.cancel} Simple invocation of method cancel

    When the view is render you'll see a simple Datatable with 2 buttons in it, one for Advancing the process state and another to Drop it.
    jboss jbpm

    So can you see the beauty of Seam ? you have already lots of built-in to manage your process: in a JBPM standalone application you have to request the JBPM Context, query the Task list, fill the Task list in a Collection, feed this collection to JSF...simply to show your task.
    When you became practical with Seam configuration file creating a JBPM tabular-data view of your process is a matter of minutes.

    Packaging your application:

    Here's a view of your ear file:
    jbpm seam


    At the root of your ear file you have the main configuration files: hibernate config file, jbpm config file and your process definition.
    Exploring further the jar and war files:
    seam jbpm integration

    Nothing new here, you should already know from the previous tutorial about seam.properties and components.xml. As said before components.xml holds the list of process definition used by this sample.

    I suggest you when you're beginning your Seam experiments to make use of the build.xml files that come with the distribution examples. There you don't have to worry about where to place your configuration files: they're already configured to go in the right place, just edit them and add classes under "src" and jsp pages ander "view".

    Conclusion


    The hard work of loading the business process definition, creating a process execution, putting the process instance in scope, transferring variables to and from the business process context, and sending signals to the process execution is hidden here behind declarative controls in the form of annotations and page descriptor tags, controls you should feel comfortable with based on your conversation experience.

    转自:http://www.mastertheboss.com/en/seam/90-seam-jbpm.html

  • 相关阅读:
    史记 · 码农列传
    死侍在新片中,扮演了一个 AI 驱动的 NPC
    什么是高中物理?一篇长长长长文告诉你!
    你管这玩意叫网络?
    你管这破玩意叫计算机?
    try-catch-finally中的4个巨坑,老程序员也搞不定!
    未来几年,软件测试九大新兴趋势
    代码中大量的if/else,你有什么优化方案?
    PHP部署服务端常见问题整理
    PHP服务端环境搭建
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6469835.html
Copyright © 2020-2023  润新知