h1. JBPM Configuration



h1. Overview

Creating business processes that coordinate people, applications, and services, JBPM brings process automation to a much wider set of business problems, from embedded workflow to enterprise business process orchestration and JBPM.

Links:
* [A tutorial about jBPM|http://www.jboss.com/products/jbpm/docs/tutorial]
* [The jBPM documentation|http://docs.jboss.com/jbpm/v3/userguide/index.html]

h1. Workflow Configuration

# workflow is packaged as a jar file. We will take the content publishing workflow which is available in the default distribution of eXo ECM. This is the standard way of creating a workflow with JBPM. See the [documentation for more information|http://docs.jboss.com/jbpm/v3/userguide/index.html].

The following file define the process :
*processdefinition.xml*
{code:xml}
<?xml version="1.0" encoding="UTF-8"?>

<process-definition name="content-publishing">

  <description>
     This process validate document then public it, and backup it when publish time is expired
  </description>

  <!- SWIMLANES ->
  <swimlane name="initiator" />
  <!- START-STATE ->
  <start-state name="start">
    <task swimlane="initiator"/>
    <event type="node-leave">
      <action class="org.exoplatform.processes.publishing.InitialActionHandler"/>
    </event>
    <transition to="evaluation"/>
  </start-state>

  <!- NODES ->
  <task-node name="evaluation">    
    <task name="evaluation" description="evaluate document">
      <assignment class="org.exoplatform.processes.publishing.ValidatorAssignmentHandler"/>
    </task>
    <transition name="approve" to="manage-publication"/>
    <transition name="disapprove" to="change-request"/>
    <transition name="delegate" to="delegate"/>
    <transition name="refuse" to="trash-movement"/>
  </task-node>

  <task-node name="change-request">
    <task name="change-request" description="update and request for validation again">
      <assignment class="org.exoplatform.processes.publishing.AuthorAssignmentHandler"/>
    </task>
    <transition name="submit" to="evaluation"/>
    <transition name="cancel" to="trash-movement"/>
  </task-node>

  <state name="trash-movement">
    <event type="node-enter">
      <action class="org.exoplatform.processes.publishing.TrashMovementActionHandler"/>
    </event>
    <transition name="move-done" to="end"/>
  </state>

  <process-state name="delegate">
    <event type="node-enter">
      <action class="org.exoplatform.processes.publishing.DelegateActionHandler"/>
    </event>
    <sub-process name="content-publishing" />
    <variable name="delegate_flg" access="read,write" mapped-name="delegate_flg" />
    <variable name="delegator" access="read,write" mapped-name="initiator" />
    <variable name="delegator" access="read,write" mapped-name="exo:validator" />
    <variable name="document-type" access="read,write" mapped-name="document-type" />
    <variable name="nodePath" access="read,write" mapped-name="nodePath" />
    <variable name="repository" access="read,write" mapped-name="repository" />
    <variable name="srcWorkspace" access="read,write" mapped-name="srcWorkspace" />
    <variable name="srcPath" access="read,write" mapped-name="srcPath" />
    <variable name="actionName" access="read,write" mapped-name="actionName" />
    <transition name="end" to="end"/>
  </process-state>

  <state name="manage-publication">
    <event type="node-enter">
      <action class="org.exoplatform.processes.publishing.SchedulePublicationTimerActionHandler"/>
    </event>
    <transition name="publication-done" to="manage-backup"/>
  </state>

  <state name="manage-backup">
    <event type="node-enter">
      <action class="org.exoplatform.processes.publishing.ScheduleBackupTimerActionHandler"/>
    </event>
    <transition name="backup-done" to="end"/>
  </state>

  <!- END-STATE ->
  <end-state name="end" />

</process-definition>
{code}

Here is the code of the *org.exoplatform.processes.publishing.ValidatorAssignmentHandler*:
{code:java}
/*
 * Copyright 2001-2003 The eXo platform SARL All rights reserved.
 * Please look at license.txt in info directory for more license detail.
 */

package org.exoplatform.processes.publishing;

import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.taskmgmt.def.AssignmentHandler;
import org.jbpm.taskmgmt.exe.Assignable;

/**
 * Created by the eXo platform team
 * User: Benjamin Mestrallet
 */
public class ValidatorAssignementHandler implements AssignmentHandler{

  public void assign(Assignable assignable, ExecutionContext executionContext) throws Exception {
    String validator = (String) executionContext.getVariable("exo:validator");
    assignable.setActorId(validator);
  }
}
{code}

Here is the code of *SchedulePublicationTimerActionHandler*.
{code:java}
/*
 * Created on Mar 24, 2005
 */
package org.exoplatform.processes.publishing;

import java.util.Date;

import org.jbpm.graph.def.Action;
import org.jbpm.graph.exe.ExecutionContext;
import org.jbpm.instantiation.Delegation;
import org.jbpm.scheduler.exe.Timer;

/**
 * @author benjaminmestrallet
 */
public class SchedulePublicationTimerActionHandler extends MoveNodeActionHandler {

  private static final long serialVersionUID = 1L;

  public void execute(ExecutionContext context) {
    Date startDate = (Date) context.getVariable("startDate");
    Date currentDate = new Date();

    if (startDate.before(currentDate)) {
      try {
        moveNode(context);
      } catch (Exception e) {
        e.printStackTrace();
      }
      context.getToken().signal("move-done");
    } else {
      //Create and save the Action object
      Delegation delegation = new Delegation();
      delegation.setClassName("org.exoplatform.processes.contentvalidation.MoveNodeActionHandler");
      delegation.setProcessDefinition(context.getProcessDefinition());

      Action moveAction = new Action();
      moveAction.setName("moveAction");
      moveAction.setActionDelegation(delegation);
      context.getProcessDefinition().addAction(moveAction);

      //create the timer
      Timer timer = new Timer(context.getToken());
      timer.setName("publicationTimer");
      timer.setDueDate(startDate);
      timer.setGraphElement(context.getEventSource());
      timer.setTaskInstance(context.getTaskInstance());
      timer.setAction(moveAction);
      timer.setTransitionName("end");
      context.getSchedulerInstance().schedule(timer);
    }
  }

}
{code}


1 eXo Configuration

First, you need to create a mixin for the workflow :

{code:xml}
  <nodeType name="exo:workflowAction" isMixin="false" hasOrderableChildNodes="false" primaryItemName="">
    <supertypes>
      <supertype>exo:businessProcessAction</supertype>
    </supertypes>
    <propertyDefinitions>
      <propertyDefinition name="exo:validator" requiredType="String" autoCreated="false" mandatory="true"
        onParentVersion="COPY" protected="false" multiple="false"/>
      <propertyDefinition name="exo:businessProcess" requiredType="String" autoCreated="true" mandatory="true"
        onParentVersion="COPY" protected="true" multiple="false"> <!-- this property is used to set the name of the workflow (the same as in processdefinition.xml) -->
        <valueConstraints/>
        <defaultValues>
          <defaultValue>content-validation</defaultValue> <!-- Here you enter the name of the workflow -->
        </defaultValues>
      </propertyDefinition>
    </propertyDefinitions>
  </nodeType>
{code}



To add your workflow to eXo you need to add this configuration to the portal.
{code:xml}
<?xml version="1.0" encoding="ISO-8859-1"?>

<configuration>
  <component>
    <key>org.exoplatform.services.workflow.WorkflowServiceContainer</key>
    <type>org.exoplatform.services.workflow.impl.jbpm.WorkflowServiceContainerImpl</type>

    <component-plugins>
      <component-plugin>
        <name>deploy.predefined.processes</name>
        <set-method>addPlugin</set-method>
        <type>org.exoplatform.services.workflow.PredefinedProcessesPlugin</type>
        <init-params>
          <object-param>
            <name>predefined.processes</name>
            <description>load of default business processes</description>
            <object type="org.exoplatform.services.workflow.ProcessesConfig">
              <field name="processLocation"><string>war:/conf/bp</string></field> <!- the location of the jars defining the workflow ->
              <field name="predefinedProcess">  <!- the jars containing the workflow ->
                <collection type="java.util.HashSet">
                  <value><string>/exo.ecm.bp.jbpm.content.validation-2.0.jar</string></value>
                </collection>
              </field>
            </object>
          </object-param>
        </init-params>
      </component-plugin>
    </component-plugins>

    <init-params>
      <value-param>
        <name>hibernate.service</name>
        <description>if  this parameter is not set or the value is empty, null or default.
          The workflow service will use the default Hibernate service.  If you modify this value,
          You need to update the external plugin as well</description>
        <value>default</value>
      </value-param>
    </init-params>
  </component>

</configuration>

{code}

The following  configuration bind the workflow to a directory.
{code:xml}
<?xml version="1.0" encoding="ISO-8859-1"?>

<configuration>
  <external-component-plugins>
    <target-component>org.exoplatform.services.cms.actions.ActionServiceContainer</target-component>
      <component-plugin>
        <name>exo:businessProcessAction</name>
        <set-method>addPlugin</set-method>
        <type>org.exoplatform.services.cms.actions.impl.BPActionPlugin</type>
        <init-params>
          <object-param>

            <name>predefined.actions</name>

            <description>description</description>

            <object type="org.exoplatform.services.cms.actions.impl.ActionConfig">

              <field  name="repository"><string>repository</string></field>

              <field  name="workspace"><string>production</string></field>

              <field  name="actions">

                <collection type="java.util.ArrayList">

                  <value>

                    <object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Action"> <!-- Init parameters that declare workspace name and actions... -->

                      <field  name="type"><string>exo:workflowAction</string></field> <!-- - The name of the mixin -->

                      <field  name="name"><string>publication</string></field>

                      <field  name="description"><string>publication workflow</string></field>

                      <field  name="srcWorkspace"><string>draft</string></field> <!-- Source Workspace: workspace that the actions will be created -->

                      <field  name="srcPath"><string>/cms/publications</string></field> <!-- Source path: Node path of action -->

                      <field  name="lifecyclePhase"><string>add</string></field>            <!-- - Lifecycle Phase: The trigger of action
(Add: Activate when have new node add to current node,
Remove: Activate when a node removed from current node,
Read: Activate when user click on custom action in this node)  -->

                      <field  name="roles"><string>*:/user</string></field>   <!-- Roles: declare permissions of users can activate action -->

                      <field  name="variables"> <!-- init variable for the workflow instance -->
                        <string>exo:validator=member:/admin</string>
                      </field>

                      <field name="mixins"> <!-- Mixins type: Collections of ActionConfig$Mixin objects, that declare name of mixins nodetype of this action and properties of this action as destWorkspace and destPath -->
                        <collection type="java.util.ArrayList">
                          <value>
                            <object type="org.exoplatform.services.cms.actions.impl.ActionConfig$Mixin">
                              <field  name="name"><string>exo:move</string></field>
                              <field  name="properties">
                                <string>exo:destWorkspace=production;exo:destPath=/cms/publications;exo:repository=repository</string>
                              </field>
                            </object>
                          </value>
                        </collection>
                      </field>

                    </object>
                  </value>
                </collection>
              </field>
            </object>
          </object-param>
        </init-params>
      </component-plugin>
 </external-component-plugins>



</configuration>

{code}
