Skip to content

JBossJBPM_as_JCL

stockiNail edited this page Oct 12, 2015 · 5 revisions

Business Process Model and Notation (BPMN)

(quoted from BPMN definition in Wikipedia)

Business Process Model and Notation (BPMN) is a graphical representation for specifying business processes in a business process model. It is also known as Business Process Modeling Notation.

Business Process Management Initiative (BPMI) developed BPMN, which has been maintained by the Object Management Group since the two organizations merged in 2005. As of March 2011, the current version of BPMN is 2.0 (in this wiki is name BPMN2.

The primary goal of BPMN is to provide a standard notation readily understandable by all business stakeholders. These include the business analysts who create and refine the processes, the technical developers responsible for implementing them, and the business managers who monitor and manage them. Consequently, BPMN serves as a common language, bridging the communication gap that frequently occurs between business process design and implementation.

The vision of BPMN 2.0 is to have one single specification for a new Business Process Model and Notation that defines the notation, metamodel and interchange format but with a modified name that still preserves the "BPMN" brand. The features include

  • Aligning BPMN with the business process definition meta model BPDM to form a single consistent language.
  • Enabling the exchange of business process models and their diagram layouts among process modeling tools to preserve semantic integrity.
  • Expand BPMN to allow model orchestrations and choreographies as stand-alone or integrated models.
  • Support the display and interchange of different perspectives on a model that allow a user to focus on specific concerns.
  • Serialize BPMN and provide XML schemes for model transformation and to extend BPMN towards business modeling and executive decision support.

Currently there are several competing standards for business process modeling languages used by modeling tools and processes. JEM uses JBoss jBPM runtime tool to execute BPMN2 workflows.

JBoss jBPM

(quoted from jBPM definition in jBPM tutorial)

jBPM is a flexible Business Process Management (BPM) Suite. It is light-weight, fully open-source (distributed under Apache Licence) and written in Java. It allows you to model, execute, and monitor business processes throughout their life cycle.

http://docs.jboss.org/jbpm/v6.1/userguide/images/Chapter-1-Overview/Process.png

A business process allows you to model your business goals by describing the steps that need to be executed to achieve those goals, and the order of those goals are depicted using a flow chart. This process greatly improves the visibility and agility of your business logic. jBPM focuses on executable business processes, which are business processes that contain enough detail so they can actually be executed on a BPM engine.

The core of jBPM is a light-weight, extensible workflow engine written in pure Java that allows you to execute business processes using the latest BPMN 2.0 specification. It can run in any Java environment, embedded in your application or as a service.

BPMN2 as JCL by jBPM runtime

JCL is finally a workflow and BPMN2 language, together jBPM runtime, is a standard workflow language which is able to executes business logic in batches approach, as well. JEM is able to execute BPMN2 file by jBPM with some restrictions:

  • Human tasks are NOT allowed, because the strength of batches is to work automatically without any human interaction.
  • Sub process (callActivity element) is not allowed.
  • jBPM workflow is executed inside JEM WITHOUT any persistence of the status

JEM leverages on jBPM BPMN2 extension creating a special work item which can use all functions provided by JEM to manage well business logic in batches (like metadata, data sets, data sources, locks).

JEM uses BPMN2 extensionElements and jBPM metaData extension elements to manage JEM properties which qualify the job and provide all information necessary to execute the job correctly (see properties section).

Installation of JEM-jBPM module

The JEM-jBPM module is not provided inside the JEM distribution. This is a special configuration that you must do to allow to manage jBPM workflows as JCLs.

To install and configure the module, have a look to the following statements:

  1. Download the JEM-jBPM module from here the distribution zip file. The module already contains all libraries of jBPM, version 6.1. Therefore no additional download are necessary.
  2. Extract the zip file in folder (name as you like). PAY ATTENTION that jBPM must be visible and accessible to all JEM nodes and, to avoid to install it on all nodes, we kindly suggest to extract the module on GFS of JEM, maybe on library folder.
  3. Configure JEM environment (inside of jem-env.xml configuration file) adding the following XML in factories element, assuming your extracted the module on JEM GFS library folder:
   <factory className="org.pepstock.jem.jbpm.JBpmFactory">
      <properties></properties>
      <classpath>
         <pathElement>${jem.library}/jem-jbpm/jem-jbpm.jar</pathElement>
         <pathElement>${jem.library}/jem-jbpm/jbpm/**</pathElement>
      </classpath>
   </factory>

Properties definition

To use BPMN2 inside JEM, BPMN2 XML JCL file must contain the mandatory and optional properties that JEM needs, described in JCL Reference, as following:

  • Job Name is optional string property, named jem.job.name . If missing, id attribute of process element will be used. If boths are missing, an exception occurs.
  • Environment is optional string property, named jem.job.environment.If missing, the JEM node environment definition is used.
  • Domain is optional string property, named jem.job.domain. If missing, default value (***) will be used.
  • Affinity is optional string property, named jem.job.affinity. If missing, default value (***) will be used.
  • User is optional string property, named jem.job.user. If missing, default value (null) will be used. An exception occurs if the user, who submitted the job, is not authorized to change the user job execution.
  • Locking Scope is optional string property, named jem.job.lockingScope. If missing, default value (job) will be used. If the value is not equals to one the possible values (job, step , task), an exception occurs. step and task ahve the same behaviour inside the jBPM. In case the workflow will use a gateway, this property will be ignored because a JOB locking scope will be used to avoid any inconsistent situation, locking resources.
  • Hold is optional boolean property, named jem.job.hold. If missing, default value (false) will be used.
  • Priority is optional integer property, named jem.job.priority. If missing, default value (10) will be used (highest priority is 1).
  • Memory is optional integer property, named jem.job.memory. If missing, default value (128) will be used. Be aware the unit is MegaBytes.
  • Classpath is optional string property, named jem.job.classPath. Defining a classpath, it will be able to import jBPM task definitions of 3rd parties. The value is a string and the files are separated by semicolons ;. If the file doesn't represent an absolute path, JEM will use relative position from jem.classpath folder. You could use variables that JEM substitutes in string value. If missing, default value (null) will be used. The paths will be added at the end of default classpath, build by JEM.
  • Prior Classpath is optional string property, named jem.job.priorClassPath. Defining a classpath, it will be able to import jBPM task definitions of 3rd parties. The value is a string and the files are separated by semicolons ;. If the file doesn't represent an absolute path, JEM will use relative position from jem.classpath folder. You could use variables that JEM substitutes in string value. If missing, default value (null) will be used. The paths will be added at the beginning of default classpath, build by JEM.
  • Emails Notification is optional string property, named jem.job.emailsNotification. If missing, default value (null) will be used.
  • Java is optional string property, named jem.job.java. If missing, JEM will use the JRE used by JEM node.

All these properties must be defined in BPMN2 extensionElements and jBPM metaData elements, as following:

<!-- Metadata inside of PROCESS element-->
<extensionElements>
	<tns:metaData name="jem.job.name">
		<tns:metaValue>JOB1</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.environment">
		<tns:metaValue>ENV1</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.domain">
		<tns:metaValue>domain</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.affinity">
		<tns:metaValue>classA</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.priority">
		<tns:metaValue>99</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.user">
		<tns:metaValue>newUSER</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.lockingScope">
		<tns:metaValue>job</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.hold">
		<tns:metaValue>true</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.memory">
		<tns:metaValue>1024</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.classPath">
		<tns:metaValue>/test/my-business-logic-lib.jar</tns:metaValue>
	</tns:metaData>
	<tns:metaData name="jem.job.java">
		<tns:metaValue>jdk7</tns:metaValue>
	</tns:metaData>

</extensionElements>

extensionElements element is defined in xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" namespace for BPMN2 definition. In the sample, tns is the name assigned to XML namespace for Drools, metaData and metaValue elements are defined in xmlns:tns="http://www.jboss.org/drools" BPMN2 jBPM extension.

JEM work item handler

To use JEM features in BPMN2, it's mandatory to use a special task which implements the work item handler, BPMN2 extension provided by jBPM. The work item handler class is org.pepstock.jem.jbpm.tasks.JemWorkItemHandler and it is not necessary to define it because JEM provides that out-of-the-box. This handler is defined a fixed name, Jem, and this label must be used in the task definition inside the BPMN2 file, as following:

  <task id="_taskID" tns:taskName="Jem" name="task name">

In the sample, tns is the name assigned to XML namespace for Drools, taskName attribute defined in xmlns:tns="http://www.jboss.org/drools" BPMN2 jBPM extension.

The JEM work item handler is able to call another JAVA class to execute the business logic. The java class to execute is defined by a a input parameter, with the key jem.workItem.className.

Here is the sample how to configure a JEM work item task with an custom class to execute:

<task id="_2" tns:taskName="Jem" name="null">
   <ioSpecification id="InputOutputSpecification_1">
      <dataInput id="_2_className" name="jem.workItem.className" />
      <inputSet id="InputSet_1">
         <dataInputRefs>_2_className</dataInputRefs>
      </inputSet>
      <outputSet id="OutputSet_1" />
   </ioSpecification>
   <dataInputAssociation id="DataInputAssociation_0">
      <targetRef>_2_className</targetRef>
      <assignment id="Assignment_0">
         <from xs:type="tFormalExpression" id="FormalExpression_5">org.pepstock.jem.jbpm.tasks.utilities.Null</from>
         <to xs:type="tFormalExpression" id="FormalExpression_6">_2_className</to>
      </assignment>
   </dataInputAssociation>
</task>

There 3 kinds of java classes which can be executed by JEM work item handler:

  • a class which implements org.pepstock.jem.jbpm.tasks.JemWorkItem interface
  • a main class, that means a class with a public static void main(String[] args) method
  • a class with a method with a specific signature (or annotation) to be executed

The class container must in the classpath, both in JEM classpath or in a specific classpath set by the jem.job.classPath property, in the process metadata.

JEM work item interface

To execute own business logic you can implement a interface, org.pepstock.jem.jbpm.tasks.JemWorkItem, with a unique method which the entry point to the business logic.

/**
 * Is a standard interface that you should extend to use the JEM work item.
 * The instance of this interface will be created by workitem and the 'execute' method will be performed.
 */
public interface JemWorkItem {
       
        /**
         * This method is called by workitem, passing the parameters defined in BPMN file
         */
        int execute(Map<String, Object> parameters) throws Exception;
}

The method has got as arguments a map of parameters defined in the task (key-value approach), defined in ioSpecification/dataInput elements of BPMN2. The method returns a return code about the result of execution. If return code is not equals to 0, don't stop the workflow execution. The return code will create a output variable (usable in other tasks) with the key jem.workItem.result. If the custom class has a failure and wants to stop the workflow execution, it's enough to throw an exception.

Java main class

To execute own business logic you can create a java main class, with a public static void main(String[] args) method. All parameters defined in the task (key-value approch), defined in ioSpecification/dataInput elements of BPMN2, will be passed to the main method, in key=value format. The value is the string representation of parameters (toString method of the objects will be called).

Here is a sample:

<task id="_2" tns:taskName="Jem" name="null">
   <ioSpecification id="InputOutputSpecification_1">
      <dataInput id="_2_className" name="jem.workItem.className" />
	  <dataInput id="_2_myParm" name="my.parameter" />
      <inputSet id="InputSet_1">
         <dataInputRefs>_2_className</dataInputRefs>
		 <dataInputRefs>_2_myParm</dataInputRefs>
      </inputSet>
      <outputSet id="OutputSet_1" />
   </ioSpecification>
   <dataInputAssociation id="DataInputAssociation_0">
      <targetRef>_2_className</targetRef>
      <assignment id="Assignment_0">
         <from xs:type="tFormalExpression" id="FormalExpression_5">org.pepstock.jem.Test</from>
         <to xs:type="tFormalExpression" id="FormalExpression_6">_2_className</to>
      </assignment>
   </dataInputAssociation>
   <dataInputAssociation id="DataInputAssociation_1">
      <targetRef>_2_myParm</targetRef>
      <assignment id="Assignment_1">
         <from xs:type="tFormalExpression" id="FormalExpression_0">This is the VALUE</from>
         <to xs:type="tFormalExpression" id="FormalExpression_1">_2_myParm</to>
      </assignment>
   </dataInputAssociation>
</task>

Here is the java class:

package org.pepstock.jem;
public class Test{
	public static void main(String[] args){
		for (String arg : args){
			System.out.println(arg); // will show  "my.parameter=This is the VALUE"
		}
	}
}

Calling a method

To execute own business logic you can create a java class with a method with one of the following signature:

  • void method-name(): this method doesn't receive any argument and doesn't return any return code. The return code is always 0.
  • void method-name(Map<String, Object> parameters): this method receives map of parameters defined in the task (key-value approach), defined in ioSpecification/dataInput elements of BPMN2 and doesn't return any return code.
  • int method-name(): this method doesn't receive any argument and returns a return code.
  • int method-name(Map<String, Object> parameters): this method receives map of parameters defined in the task (key-value approach), defined in ioSpecification/dataInput elements of BPMN2 and return a return code.

If any failure will happen during the business logic and you want to stop the execution, an exception must be thrown.

It's mandatory to indicate which method JEM must call, adding the method to the class name in the input parameter. The class name and method name must separated by #, as used in the javadoc syntax.

Here is a sample:

<task id="_2" tns:taskName="Jem" name="null">
   <ioSpecification id="InputOutputSpecification_1">
      <dataInput id="_2_className" name="jem.workItem.className" />
	  <dataInput id="_2_myParm" name="my.parameter" />
      <inputSet id="InputSet_1">
         <dataInputRefs>_2_className</dataInputRefs>
		 <dataInputRefs>_2_myParm</dataInputRefs>
      </inputSet>
      <outputSet id="OutputSet_1" />
   </ioSpecification>
   <dataInputAssociation id="DataInputAssociation_0">
      <targetRef>_2_className</targetRef>
      <assignment id="Assignment_0">
         <from xs:type="tFormalExpression" id="FormalExpression_5">org.pepstock.jem.Test#execute</from>
         <to xs:type="tFormalExpression" id="FormalExpression_6">_2_className</to>
      </assignment>
   </dataInputAssociation>
   <dataInputAssociation id="DataInputAssociation_1">
      <targetRef>_2_myParm</targetRef>
      <assignment id="Assignment_1">
         <from xs:type="tFormalExpression" id="FormalExpression_0">This is the VALUE</from>
         <to xs:type="tFormalExpression" id="FormalExpression_1">_2_myParm</to>
      </assignment>
   </dataInputAssociation>
</task>

Here is the java class:

package org.pepstock.jem;
public class Test{

	private boolean error = false;

	public int execute(Map<String, Object> args){
		System.out.println(rags.get("my.parameter")); // will show "This is the VALUE"
		if (error){
			throw new RuntimeException("Error!");
		}
		return 0;
	}
}

Calling a method by annotation

JEM provides an annotation, @ToBeExecuted that you could put in your code to specify which method of your class must be executed. This annotation allows you do not specify the method name in your JCL (ONLY class name). Pay attention that you you speficy the method name in the JCL, the annotation in your code will be ignored. Furthermore, if you put more than one @ToBeExecuted annotation in your code, JEM will take the first one.

Be aware that the method must be signed as described on the previous section.

Here is a sample:

<task id="_2" tns:taskName="Jem" name="null">
   <ioSpecification id="InputOutputSpecification_1">
      <dataInput id="_2_className" name="jem.workItem.className" />
	  <dataInput id="_2_myParm" name="my.parameter" />
      <inputSet id="InputSet_1">
         <dataInputRefs>_2_className</dataInputRefs>
		 <dataInputRefs>_2_myParm</dataInputRefs>
      </inputSet>
      <outputSet id="OutputSet_1" />
   </ioSpecification>
   <dataInputAssociation id="DataInputAssociation_0">
      <targetRef>_2_className</targetRef>
      <assignment id="Assignment_0">
         <from xs:type="tFormalExpression" id="FormalExpression_5">org.pepstock.jem.Test</from>
         <to xs:type="tFormalExpression" id="FormalExpression_6">_2_className</to>
      </assignment>
   </dataInputAssociation>
   <dataInputAssociation id="DataInputAssociation_1">
      <targetRef>_2_myParm</targetRef>
      <assignment id="Assignment_1">
         <from xs:type="tFormalExpression" id="FormalExpression_0">This is the VALUE</from>
         <to xs:type="tFormalExpression" id="FormalExpression_1">_2_myParm</to>
      </assignment>
   </dataInputAssociation>
</task>

Here is the java class:

package org.pepstock.jem;
public class Test{

	private boolean error = false;

    @ToBeExecuted
	public int execute(Map<String, Object> args){
		System.out.println(rags.get("my.parameter")); // will show "This is the VALUE"
		if (error){
			throw new RuntimeException("Error!");
		}
		return 0;
	}
}

Data descriptions and datasets

Data descriptions are implemented by specific data input (inside of IOSpecification element) for task of Jem type (means which will execute JemWorkItemHandler). The data descriptions are defined using a specific name of a data input. All data descriptions parameters definition must be have a name with jem.dataDescription. prefix. The name of data description, is mandatory, is the string after the prefix.

Here is a sample:

<ioSpecification id="InputOutputSpecification_2_1">
	...
	<dataInput id="_2_input" name="jem.dataDescription.INPUT" />
	<dataInput id="_2_output" name="jem.dataDescription.OUTPUT" />
	<inputSet id="InputSet_2_1">
		<dataInputRefs>_2_input</dataInputRefs>
		<dataInputRefs>_2_output</dataInputRefs>
	</inputSet>
	...
</ioSpecification>

In this case, we're defining 2 data descriptions, with names INPUT and OUTPUT. This name is used inside the business logic to access to datasets by JNDI so this name must be unique in the task definition.

Datasets and SYSOUT data description are defined using a special syntax as value of these parameters.

	SYSOUT,DISP=NEW
	DSN=file-name,DISP=NEW|SHR|OLD|MOD
	DSN=(file-name1;file-name2),DISP=SHR
	DSN=file-name,DISP=NEW|SHR|OLD|MOD,DATASOURCE=datasource
	DSN=*.task-id.data-description-name,DISP=SHR|OLD|MOD

A sysout token must be used if you need a sysout data description. Only disposition NEW must be used The DISP tokne defines which mode you want to use on the datasets and must be a valid value, one of the following string enumeration: NEW, MOD, OLD or SHR.

Datasets name (identified by DSN) could be related to:

  • a single resource.
  • multi resources. All resources must be defined inside brackets, semicolon separated.
  • a reference to another resource, defined in another task

Datasets could represent:

  • file name (absolute or relative path), composed by properties if necessary. If it's a relative path, JEM adds the mount point path, based on the mutli data path configuration, used to identify the global file system with all data.
  • GDG file name, following the same rules of a normal file name (see previous item).
  • Reference to another data set in another data description, not in the same task as well. The syntax is: .task-id.data-description-name
  • Temporary prefix file name

Datasets could have the DATASOURCE token which could represent a relation with a data source, previously defined. It works only the FTP resources and the name of dataset represents the file to manage by FTP.

Here is a sample where a custom class copy all the content from a data description (named INPUT) to another one (named OUTPUT):

<!-- Copy task -->
<task id="_2" tns:taskName="Jem" name="Copy Task">
	<ioSpecification id="InputOutputSpecification_1">
		<dataInput id="_2_className" name="jem.workItem.className" />
		<dataInput id="_2_input" name="jem.dataDescription.INPUT" />
		<dataInput id="_2_output" name="jem.dataDescription.OUTPUT" />
		<inputSet id="InputSet_1">
			<dataInputRefs>_2_input</dataInputRefs>
			<dataInputRefs>_2_output</dataInputRefs>
		</inputSet>
		<outputSet id="OutputSet_1" />
	</ioSpecification>
	<dataInputAssociation id="DataInputAssociation_0">
		<targetRef>_2_className</targetRef>
		<assignment id="Assignment_0">
			<from xs:type="tFormalExpression" id="FormalExpression_5">org.pepstock.jem.jbpm.tasks.utilities.Copy</from>
			<to xs:type="tFormalExpression" id="FormalExpression_6">_2_className</to>
		</assignment>
	</dataInputAssociation>
	<dataInputAssociation id="DataInputAssociation_1">
		<targetRef>_2_input</targetRef>
		<assignment id="Assignment_1">
			<from xs:type="tFormalExpression" id="FormalExpression_1">DSN=gdg/jemtest(0),DISP=SHR</from>
			<to xs:type="tFormalExpression" id="FormalExpression_2">_2_input</to>
		</assignment>
	</dataInputAssociation>
	<dataInputAssociation id="DataInputAssociation_2">
		<targetRef>_2_output</targetRef>
		<assignment id="Assignment_2">
			<from xs:type="tFormalExpression" id="FormalExpression_3">DSN=gdg/jemtest(+1),DISP=NEW</from>
			<to xs:type="tFormalExpression" id="FormalExpression_4">_2_output</to>
		</assignment>
	</dataInputAssociation>
</task>

Here is the java code, which performs the copy:

/**
 * JEM work item that copies a file or list of files (data description named INPUT) on other one (data description named OUTPUT).
 */
public class Copy implements JemWorkItem {
       
        /**
         * Data description name for files in INPUT
         */
        private static final String INPUT_DATA_DESCRIPTION_NAME = "INPUT";
       
        /**
         * Data description name for files in OUTPUT
         */
        private static final String OUTPUT_DATA_DESCRIPTION_NAME = "OUTPUT";

        /* (non-Javadoc)
         */
        @Override
        public int execute(Map<String, Object> parameters) throws Exception {
                // new initial context to access by JNDI to COMMAND DataDescription
                // If you don't to have a dependency to JEM (in development phase) you can use this different code
                // to get the InitialContext:
                // Hashtable<String, String> env = new Hashtable<String, String>();
                // env.put(Context.INITIAL_CONTEXT_FACTORY, "org.pepstock.jem.node.tasks.jndi.JemContextFactory");
                // InitialContext context = new InitialContext(env);

                //
                //
                InitialContext ic = ContextUtils.getContext();
                // gets inputstream
                Object input = (Object) ic.lookup(INPUT_DATA_DESCRIPTION_NAME);
                // gets outputstream
                Object output = (Object) ic.lookup(OUTPUT_DATA_DESCRIPTION_NAME);

                InputStream istream = null;
                OutputStream ostream = null;

                // checks if object is a inputstream otherwise error
                if (input instanceof InputStream){
                        istream = (InputStream) input;
                } else {
                        throw new MessageException(JBpmMessage.JEMM017E, INPUT_DATA_DESCRIPTION_NAME, input.getClass().getName());
                }
                // checks if object is a outputstream otherwise error
                if (output instanceof OutputStream){
                        ostream = (OutputStream) output;
                } else {
                        IOUtils.closeQuietly(istream);
                        throw new MessageException(JBpmMessage.JEMM016E, OUTPUT_DATA_DESCRIPTION_NAME, output.getClass().getName());
                }

                // copy
                int bytes = IOUtils.copy(istream, ostream);
                IOUtils.closeQuietly(istream);
                IOUtils.closeQuietly(ostream);
                LogAppl.getInstance().emit(JBpmMessage.JEMM062I, bytes);

                return Result.SUCCESS;
        }

}

Data sources

Data sources are implemented by specific data input (inside of IOSpecification element) for task of Jem type (means which will execute JemWorkItemHandler). The data sources are defined using a specific name of a data input. All data sources parameters definition must be have a name with jem.dataSource. prefix. The name of data source, is mandatory, is the string after the prefix.

Here is a sample:

<ioSpecification id="InputOutputSpecification_2_1">
	...
	<dataInput id="_2_ds" name="jem.dataSource.FTPlocalhost" />
	<inputSet id="InputSet_2_1">
		<dataInputRefs>_2_ds</dataInputRefs>
	</inputSet>
	...
</ioSpecification>

In this case, we're defining a data source, with name FTPlocalhost. This name is used inside the business logic to access to datasets by JNDI so this name must be unique in the task definition.

The syntax to use to define the data source attributes for the task is following:

	RESOURCE=resource-name
	RESOURCE=resource-name,PROPERTIES=(key1=value1; key2=value2)

With the RESOURCE token, you can specify the name of the resource defined in JEM. If missing, JEM uses the data sources name as name of resource. For many datasources, you can override some properties (for instance binary property for a FTP connection) using the PROPERTIES token with the list of the properties (in key=value format) inside brackets, semicolon separated.

Here is a sample how you can copy a file from a FTP connection (name is FTPlocalhost), where this resource is already defined inside JEM:

<!-- Copy task -->
<task id="_2" tns:taskName="Jem" name="Copy Task">
	<ioSpecification id="InputOutputSpecification_1">
		<dataInput id="_2_className" name="jem.workItem.className" />
		<dataInput id="_2_input" name="jem.dataDescription.INPUT" />
		<dataInput id="_2_output" name="jem.dataDescription.OUTPUT" />
		<dataInput id="_2_ds" name="jem.dataSource.FTPlocalhost" />
		<inputSet id="InputSet_1">
			<dataInputRefs>_2_input</dataInputRefs>
			<dataInputRefs>_2_output</dataInputRefs>
			<dataInputRefs>_2_ds</dataInputRefs>
		</inputSet>
		<outputSet id="OutputSet_1" />
	</ioSpecification>
	<dataInputAssociation id="DataInputAssociation_0">
		<targetRef>_2_className</targetRef>
		<assignment id="Assignment_0">
			<from xs:type="tFormalExpression" id="FormalExpression_5">org.pepstock.jem.jbpm.tasks.utilities.Copy</from>
			<to xs:type="tFormalExpression" id="FormalExpression_6">_2_className</to>
		</assignment>
	</dataInputAssociation>
	<dataInputAssociation id="DataInputAssociation_1">
		<targetRef>_2_input</targetRef>
		<assignment id="Assignment_1">
			<from xs:type="tFormalExpression" id="FormalExpression_1">DATASOURCE=FTPlocalhost,DSN=sample.data,DISP=SHR</from>
			<to xs:type="tFormalExpression" id="FormalExpression_2">_2_input</to>
		</assignment>
	</dataInputAssociation>
	<dataInputAssociation id="DataInputAssociation_2">
		<targetRef>_2_output</targetRef>
		<assignment id="Assignment_2">
			<from xs:type="tFormalExpression" id="FormalExpression_3">DSN=gdg/jemtest(+1),DISP=NEW</from>
			<to xs:type="tFormalExpression" id="FormalExpression_4">_2_output</to>
		</assignment>
	</dataInputAssociation>
	<dataInputAssociation id="DataInputAssociation_3">
		<targetRef>_2_ds</targetRef>
		<assignment id="Assignment_3">
			<from xs:type="tFormalExpression" id="FormalExpression_7">RESOURCE=FTPlocalhost</from>
			<to xs:type="tFormalExpression" id="FormalExpression_8">_2_ds</to>
		</assignment>
	</dataInputAssociation>
</task>

Locks

Locks are implemented by specific data input (inside of IOSpecification element) for task of Jem type (means which will execute JemWorkItemHandler). The locks are defined using a specific name of a data input, called jem.locks.

Here is a sample:

<ioSpecification id="InputOutputSpecification_2_1">
	...
	<dataInput id="_2_locks" name="jem.locks" />
	<inputSet id="InputSet_2_1">
		<dataInputRefs>_2_locks</dataInputRefs>
	</inputSet>
	...
</ioSpecification>
<dataInputAssociation id="DataInputAssociation_0">
	<targetRef>_2_locks</targetRef>
	<assignment id="Assignment_0">
		<from xs:type="tFormalExpression" id="FormalExpression_5">LOCKNAME1, LOCKNAME2, LOCKNAME3</from>
		<to xs:type="tFormalExpression" id="FormalExpression_6">_2_locks</to>
	</assignment>
</dataInputAssociation>

The locks names are defined as value of this parameter. The list of names is a string with all names, comma separated. In the above sample, JEM will creates 3 locks, using the names in the assignment.

Using BPMN2 Modeler to design your batch

(quoted from BPMN2 Modeler definition in BPMN2 modeler main site)

The BPMN2 Modeler is a graphical modeling tool which allows creation and editing of BPMN ( Business Process Modeling Notation ) diagrams. The tool is built on Eclipse and uses the BPMN 2.0 EMF meta model currently being developed within the Eclipse Model Development Tools (MDT) project. This meta model is compatible with the BPMN 2.0 specification proposed by the Object Management Group.

http://eclipse.org/bpmn2-modeler/images/snapshots.gif

How to install BPMN2 modeler

To install BPMN2 modeler, go to the BPMN2 modeler main site and follow all instructions to install in Ecplise.

Quickly, open Eclipse, select Help --> Install new software.... Insert in the highlighted text field one of the URLs list published in modeler site.

http://www.pepstock.org/resources/Eclipse-Install.png

More info about the modeler are here.

How to install and configure JEM-jBPM module

First of all you need a Eclipse project. Remember that you can write your code without having JEM-jBPM module in your project. But it could be helpful to have if you want to add to BPMN2 modeler palette the JEM task.

Befiore installing the JEM module, go to Eclipse menu, Windows menu and Preferences item. Choose BPMN2 item on the menu and in Editor/Tool profiles, you must choose JBoss jBPM Business Process Engine as target runtime.

http://www.pepstock.org/resources/Eclipse-JBPMruntime.png

To install and configure the module, have a look to the following statements:

  1. Download the JEM-jBPM module from here the distribution zip file. The module already contains all libraries of jBPM, version 6.1, and the additional configuation to add JEM task to the palette. Therefore no additional download are necessary.
  2. Extract the zip file in project folder (name as you like).
  3. Refresh your Eclipse project to load new files.

Now opening the diagram editor, you should have in the palette in the custom task tab, the JEM task definition, as following:

http://www.pepstock.org/resources/EclipseModelerPalette.png

Now you are ready to write your business logic, using BPMN2, jBPM and JEM.

How to use JEM task in your diagrams

After creating a new diagram, using BPMN2 modeler, you can add to your workflow the Jem task. When you inspect the task, you can add all necessary parameters to:

  • define the class that JemWorkItemHandler must execute (JEM task configuration has already define the parameter name or the classname). Use the info here how to add the classname parameter
  • define all necessary data descriptions (adding parameters to the task, as is described here)
  • define all necessary data sources (adding parameters to the task, as is described here)
  • define all necessary locks (adding parameters to the task, as is described here)

Configuring a BPMN workflow with JEM parameters

To open a workflow with th diagram editor, go to menu and by Open With choose Bpmn2 Diagram Editor:

http://www.pepstock.org/resources/CompleteWrokFlow.png

Inspesting the single task, you can see the Description folder where it's important to see that is a JEM task.

http://www.pepstock.org/resources/DescriptionTask.png

Let's configure the JEM paramenters. A mandatory paramenter for a JEM task is the class name of custom code to be executed. Therefore it's mandatory to set the class name. To do that, follow the above instructions to set a data description because the way to set the value of the parameter is the same for all JEM parameters.

http://www.pepstock.org/resources/IOParameters.png

To add data descriptions, data sources or locks to the JEM task:

  1. click of green plus
  2. in the "Input Parameter Mapping Details", chose Expression option
  3. choose Script Language" to blank (first item)
  4. put in the text area, named "Script", the information to set data descriptions, data sources or locks.
  5. set parameter name, on the text field named "Name".
  6. leave empty the paratemeter type
  7. press OK to add the parameter

http://www.pepstock.org/resources/JemParameters.png

Configuring a BPMN workflow with JEM properties

To open a workflow with th model editor, go to menu and by Open With choose Bpmn2 Model Editor:

http://www.pepstock.org/resources/ModelEditor.png

With the model editor, you can see your workflow in a tree format but, more important, give you the possibilties to add the process metadata, used by JEM to schedule the job.

As outlined in the picture, expanding the tree, inside the Extension node you can add, update and remove JEM properties (details here).

Clone this wiki locally