Java Business Process Management |
jPdl Reference ManualThis page describes the schema of the processdefinition.xml file.The process archiveA process archive is a formal description of a business process. It is packaged
as a jar-formatted file, usually with an extension
Versioning mechanismBasically, the versioning mechanism of jBpm comes down to the following principles :
The schema of processdefinition.xmlDocument type definition<!DOCTYPE process-definition PUBLIC "-//jBpm/jBpm Mapping DTD 2.0 beta3//EN" "http://jbpm.org/dtd/processdefinition-2.0-beta3.dtd">the document type definition of processdefinition.xml process-definition<!ELEMENT process-definition ( description?, swimlane*, type*, start-state, ( state | milestone | process-state | decision | fork | join )*, end-state, action* ) > <!ATTLIST process-definition name CDATA #REQUIRED >dtd fragment for process-definition state<!ELEMENT state ( description?, assignment?, action*, transition+ ) > <!ATTLIST state name CDATA #REQUIRED >dtd fragment for a state In jBpm the term state has the same meaning as in finite state machines (FSM) or UML state diagrams. The purpose of modelling a business process in jBpm is to create a software system. We consider the process definition as a part of the software system being build. So the term state in jBpm is to be interpreted from the viewpoint of the software system of which jBpm is a part. State is the central concept of jBpm. When starting to model a process in jBpm, the first thing to do is think about the states of the process. The states will serve as the basic framework of your process. There is a very specific reason why jBpm is centered around the state concept. That is because state does not have a counterpart in programming languages. A software program is either running or it is not. A business process typically has related pieces of programming logic that are executed separately. jBpm allows to model these states between the related pieces of programming logic. jPdl also defines control flow between the states with transitions, decisions, forks, joins and milestones. Note that the control flow defined between states. Wherever plain programming logic is more appropriate, process developers can specify an action on a process event. The phylisofy of jPdl is to extend java with state management and have the least overlap with programming language capabilities. This differentiates jPdl from other business process languages such as e.g. BPEL. Other process languages do not make that clear separation. assignment<ELEMENT assignment EMPTY > <!ATTLIST assignment swimlane CDATA #IMPLIED assignment (optional|required) #IMPLIED authentication (optional|required|verify) #IMPLIED >dtd fragment for an assignment When a process execution arrives in a state, the workflow engine will wait until it is given an external trigger (with the jBpm API method ExecutionService.endOfState(...)). Inside that method, jBpm will calculate the next state of the process instance. So a state can be seen as a dependancy upon an external actor. The external actor can be a human, a group or a system. There are numerous ways how states in a business process can relate to tasks which basically can be divided into two groups : Client based assignmentIn this strategy, users of jBpm will manage the tasklists for their users themselves. jBpm is in this case only used as an execution engine for finite state machines. jBpm's responsibility is to calculate and keep track of the state of process executions, while it is the responsability of the client to make sure that everybody knows what to do. Clients then typically want to find all process instances (or tokens) in a given state.Process based assignment(this was to only assignment strategy supported before jbpm 2.0 beta3)In this assignment strategy, jBpm will be responsible for assigning states to actors and keep track of the tasklists. In jBpm, the progress during execution of a process is tracked with a token. A token has a pointer to a state and to an actor. In jBpm an actor is always referenced with a plain java.lang.String . To specify how jBpm must assign tokens
to actors, several events are relevant. Let's go over them one by one :
Whenever a client starts a new process instance or signals the end of a state, jBpm starts calculating the next state for a process instance. The first thing we want to mention about assignments is that the first parameter of these API method calls is the actor. That parameter is used to specify on who's behalf the method is executed. In case of starting a new process instance, a root-token is created in the start-state. In case of an endOfState, a tokenId needs to be specified as a parameter which is in some state. Then, jBpm will start calculating the new state for the token. For simplicity we will ignore concurrency for a moment. The token will travel over transitions and nodes until it arrives in a state node. At that moment, the token needs to be assigned to an actor. After the selection of the actor, jBpm will associate the selected actor with the token and the invoked method (startProcessInstance or endOfState) will return. So when a token in a state has a reference to an actor, that means that execution of that process instance is waiting for that actor to provide an external trigger to the jBpm engine. In this case, a state in the process corresponds to a task for a user. jBpm calculates the tasklist by searching for all tokens that are assigned to the given actor. Now, the actor can select a token from the list and signal the end of state again. Assignment has to more attributes that are not yet covered : For more about coping with group assignments, see the faqs. swimlane<!ELEMENT swimlane ( description?, delegation? ) > <!ATTLIST swimlane name CDATA #REQUIRED >dtd fragment for swimlane Typically, one person is responsible for multiple states in one process. In jBpm this is expressed by creating a swimlane and assigning all states for that actor to the swimlane. A swimlane in a business process can be seen as a role-name for an actor within the process. The jBpm interpretation of swimlane corresponds to the term swimlane used in UML 1.5. The first time when execution arrives in a state for a given swimlane, the actor is calculated. public interface AssignmentHandler { String selectActor( AssignmentContext assignerContext ); }the AssignmentHandler interface The delegation tag within a swimlane references an implementation of AssignmentHandler. Then that actor is stored in a process variable with the same name as the swimlane. Next time when the process arrives in a state for the given swimlane, the jBpm engine will notice the variable and assign the token to the actor which was stored in the variable. So swimlanes are defined on a process level and states reference swimlanes in the assignment. The result of this calculation will be stored in a process variable with the same name as the swimlane. So then when the next state is reached of the same swimlane, that state is assigned to the same actor without using the AssignmentHandler again. Because the relation between a swimlane and the actor is stored in a variable, it is possible to manipulate that relation by updating the variable. variable and type<!ELEMENT type ( description?, (delegation|transient), variable* ) > <!ATTLIST type java-type CDATA #IMPLIED > <!ELEMENT transient EMPTY > <!ELEMENT variable EMPTY > <!ATTLIST variable name CDATA #REQUIRED >dtd fragment for type and variable VariablesA variable is a key-value pair associated with a process instance (=one process execution).
The key is a Variables store the context information of a process instance. Variables can be set in 3 ways :
When working with variables we have tried to mimic as much as possible the semantics of a java.util.Map thoughout the jBpm-API, . This means that a variable is only instantiated when it is inserted (read: set) and that any java-type can be used as value. TypeA type specifies how jBpm should store the value of a variable in the database. jBpm has a text field for storing values so the conversion between text and object is done with a Serializer : public interface Serializer { String serialize( Object object ); Object deserialize( String text ); }the Serializer interface A type can be seen as a reference to a Serializer. jBpm includes default Serializer implementations for following java-types : java.lang.String java.lang.Long java.lang.Doubleby default supported java-types Variable-type matchingVariables with a java-type that is supported by default do not have to be declared in the
processdefinition.xml. jBpm has a semi automatic typing mechanism : When a variable is
instantiated jBpm tries to calculate the type of the variable by examining the java-type
of the variable value. If the variable-value is a default supported java-type, that type
is used. Else, jBpm checks if the java-type of the variable-value corresponds with a type
declared in the processdefinition.xml (attribute Transient variablesSome variables do not need to be made persistent in the database. A variable 'to.email.address' is being provided as a variable in an endOfState() call to the jBpm-API. The state has one leaving transition with an action that sends an email to the given address. If that was the only usage of the variable 'to.email.address' it would not have to be made persistent. For this purpose, jBpm supports transient variables. Transient variables are not stored in the database and can only be used inside the jBpm-API method call they're being supplied. In other words, the scope of transient variables is a jBpm-API method call.start-state<!ELEMENT start-state ( description?, transition+ ) > <!ATTLIST start-state name CDATA #REQUIRED swimlane CDATA #IMPLIED >dtd fragment for start-state The start-state is the unique state in a process from which all process instances start. Note that at process-instance-start-time you can already feed variables in the process. Another important concept is that you can have multiple transitions leaving the start-state. In that case, you need to specify which transition should be taken when you start a process instance. milestone<!ELEMENT milestone ( description?, action*, transition ) > <!ATTLIST milestone name CDATA #REQUIRED>dtd fragment for a milestone A milestone is a special kind of state that can be used for synchronizing between
two concurrent paths of execution. A milestone can be used in a situation where
one path of execution needs to wait upon an event in another path of execution.
If the milestone was not reached, execution has to wait in the milestone state until
the other concurrent path of execution has reached the milestone. If the milestone
was already reached, the execution just passes through the milestone state.
For more information on milestones and a graphical animation, see
the workflow patterns.
A milestone state is related with one or more actions that signal the reaching of a
milestone. Those actions can be modelled in the process with the default ActionHandler :
... <milestone name="theMilestone"> <transition to="stateAfterMilestone" /> </milestone> ... <state name="stateBeforeReachingMilestone" swimlane="initiator"> <transition to="stateAfterReachingMilestone"> <action> <delegation class="org.jbpm.delegation.action.MilestoneReachedActionHandler">theMilestone</delegation> </action> </transition> </state> ...modelling a milestone in the processdefinition.xml process-state<!ELEMENT process-state ( description?, delegation, action*, transition+ ) > <!ATTLIST process-state name CDATA #REQUIRED>dtd fragment for a process-state A process state corresponds to the invocation of a super-process. The parent process starts a sub-process when execution arrives in the process-state. The process remains in the process-state for the duration of the sub-process. When the sub-process finishes, the process-state is left. decision<!ELEMENT decision ( description?, delegation, action*, transition+ ) > <!ATTLIST decision name CDATA #REQUIRED>dtd fragment for a decision A decision decides between multiple paths of execution which are exclusive. If you're a programmer, just think of it as an if-then-else construct. Of course, a decision can have as many leaving transitions as desired. Note that a decision models a situation where the workflow engine decides which route to take based upon the context (= variables) and perhaps some external resources. As an alternative, you can model multiple transitions leaving a state. In that case, the jBpm client must decide which of the leaving transitions to take by including the selected transition name as a parameter in the endOfState method invocation. fork<!ELEMENT fork ( description?, delegation?, action*, transition+ ) > <!ATTLIST fork name CDATA #REQUIRED corresponding-join CDATA #IMPLIED>dtd fragment for a fork A fork spawns multiple concurrent paths of execution. It is possible to specify custom fork behaviour with the ForkHandler interface. But the default behaviour (when no delegation is specified in the fork) is that one child-token is spawned for every leaving transition of the fork. So only for advanced exotic concurrency you'll need to implement a custom ForkHandler. Normally, a fork has a related join which defines a concurrency block. With the default fork and join behaviour supports only strict nesting. The default fork and join do not support transitions that cross concurrency block boundaries. public interface ForkHandler { void fork( ForkContext forkContext ) throws ExecutionException; }the ForkHandler interface join<!ELEMENT join ( description?, delegation?, action*, transition ) > <!ATTLIST join name CDATA #REQUIRED corresponding-fork CDATA #IMPLIED>dtd fragment for a join A fork joins multiple concurrent paths of execution. It is possible to specify custom join behaviour with the JoinHandler interface. But the default behaviour (when no delegation is specified in the join) is that all tokens that have been spawned together in the corresponding fork. The last token to arrive in the join will trigger the parent token to proceed over the leaving transition of the join. So only for advanced exotic concurrency you'll need to implement a custom JoinHandler. Constraint : a join can only have one leaving transition. public interface JoinHandler { void join( JoinContext joinContext ) throws ExecutionException; }the JoinHandler interface end-state<!ELEMENT end-state EMPTY > <!ATTLIST end-state name CDATA #REQUIRED>dtd fragment for end-state A process-definition has exactly one end-state. When the execution of a process instance arrives in the end-state, the process instance is finished. transition<!ELEMENT transition ( action* )> <!ATTLIST transition name CDATA #IMPLIED to CDATA #REQUIRED>dtd fragment for a transition Transitions specify directed connections between nodes. The transition element should be put inside the node from which the transition leaves. action<!ELEMENT action ( delegation ) > <!ATTLIST action event-type (process-start|process-end| state-enter|state-leave|state-after-assignment| milestone-enter|milestone-leave| decision-enter|decision-leave| fork-enter|fork-every-leave| join-every-enter|join-leave| transition) #IMPLIED>dtd fragment for an action An action is a piece of java code that can be executed by the workflow engine upon an event during process execution. The
public interface ActionHandler { void execute( ExecutionContext executionContext ); }the ActionHandler interface delegation<!ELEMENT delegation ( #PCDATA ) > <!ATTLIST delegation class CDATA #REQUIRED>dtd fragment for a delegation TODO : explain the link between the containing element and the interface the delegation class has to implement. Other process archive filesWhen a process archive is deployed, the processdefinition.xml is parsed and that information
is stored in the jbpm database. All other files you add into the process archive are
stored in the db or in the file-system and associated with the process definition that is created.
As a client of the jbpm API you can access those files with |