From do-not-reply at jboss.org Sun Oct 17 10:44:29 2010 Content-Type: multipart/mixed; boundary="===============2819330918473443660==" MIME-Version: 1.0 From: do-not-reply at jboss.org To: jbpm-commits at lists.jboss.org Subject: [jbpm-commits] JBoss JBPM SVN: r6765 - in jbpm4/trunk/modules: devguide/src/main/docbook/en/modules and 2 other directories. Date: Sun, 17 Oct 2010 10:44:29 -0400 Message-ID: <201010171444.o9HEiTxg015808@svn01.web.mwc.hst.phx2.redhat.com> --===============2819330918473443660== Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Author: rebody Date: 2010-10-17 10:44:27 -0400 (Sun, 17 Oct 2010) New Revision: 6765 Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.j= ava jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/deployment/= Bpmn2DeploymentTest.java jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent/= TimerStartEventTest.java Log: JBPM-2830 change the strategy of BPMN name and key convertion Modified: jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnP= arser.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.= java 2010-10-16 13:44:02 UTC (rev 6764) +++ jbpm4/trunk/modules/bpmn/src/main/java/org/jbpm/bpmn/parser/BpmnParser.= java 2010-10-17 14:44:27 UTC (rev 6765) @@ -105,14 +105,15 @@ String id =3D XmlUtil.attribute(processElement, "id", parse); String name =3D XmlUtil.attribute(processElement, "name"); = - if (id !=3D null && !"".equals(id)) { - processDefinition.setName(id); - } else { + if (id =3D=3D null || "".equals(id.trim())) { parse.addProblem("Process has no or an empty id"); } = if (name !=3D null) { - processDefinition.setKey(name); + processDefinition.setName(name); + processDefinition.setKey(id); + } else { + processDefinition.setName(id); } = Element descriptionElement =3D XmlUtil.element(processElement, "docu= mentation"); Modified: jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpm= n2.xml =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml= 2010-10-16 13:44:02 UTC (rev 6764) +++ jbpm4/trunk/modules/devguide/src/main/docbook/en/modules/ch03-Bpmn2.xml= 2010-10-17 14:44:27 UTC (rev 6765) @@ -1,63 +1,63 @@ - = + BPMN 2.0 - = +
- = + What is BPMN 2.0? - = + - The Business Process Modeling Notation (BPMN) is a standard for the - graphical notation of business process models. The standard is - maitained by the Object Management Group (OMG). - - = - Basically, the BPMN specification defines how a task must look like, wh= ich constructs can - be connected to each other, etc. in a meaning that cannot be - misinterpreted. - + The Business Process Modeling Notation (BPMN) is a standard fo= r the + graphical notation of business process models. The standard is + maitained by the Object Management Group (OMG). + + + Basically, the BPMN specification defines how a task must look= like, which constructs can + be connected to each other, etc. in a meaning that cannot be + misinterpreted. + - Earlier versions of the standard (<=3D version 1.2) are limited to= the modeling - only, aiming at a common understanding between all stakeholders - involved in documenting, discussing and implementing business - processes. The BPMN standard has proven itself, as many modeling tools - on the market today use the symbols and constructs specified in the - BPMN standard. In fact, the current JPDL designer also uses BPMN - symbols. - + Earlier versions of the standard (<=3D version 1.2) are limited= to the modeling + only, aiming at a common understanding between all stakeholders + involved in documenting, discussing and implementing business + processes. The BPMN standard has proven itself, as many modeli= ng tools + on the market today use the symbols and constructs specified i= n the + BPMN standard. In fact, the current JPDL designer also uses BP= MN + symbols. + - Version 2.0 of the BPMN specification, which is currently in finalizat= ion phase and is - scheduled to be finished soon, allows to add precise technical - details to the shapes and symbols available in BPMN and at the same - time specify what the execution semantics of BPMN 'elements' are. By - using an XML language to specify the executable semantics of a business - process, the BPMN specification has evolved into a language for - business processes that can be executed on any BPMN2 compliant process - engine - while still having the powerful graphical notation. + Version 2.0 of the BPMN specification, which is currently in fin= alization phase and is + scheduled to be finished soon, allows to add precise technical + details to the shapes and symbols available in BPMN and at the= same + time specify what the execution semantics of BPMN 'elements' a= re. By + using an XML language to specify the executable semantics of a= business + process, the BPMN specification has evolved into a language for + business processes that can be executed on any BPMN2 compliant= process + engine - while still having the powerful graphical notation. - = +
- = +
- = + History and goal - = + - The jBPM BPMN2 implementation was started in close collaboration with t= he - community in augustus 2009 after releasing jBPM 4.0. = - Later, it was decided that the first release (ie documented/QA'd) to - incorporate parts of the BPMN2 spec would be jBPM 4.3. - + The jBPM BPMN2 implementation was started in close collaborati= on with the + community in augustus 2009 after releasing jBPM 4.0. + Later, it was decided that the first release (ie documented/QA= 'd) to + incorporate parts of the BPMN2 spec would be jBPM 4.3. + - The goal of this effort is to build a native BP= MN2 runtime engine - (or better said implementing 'BPMN2 exectuable') leveraging the Process - Virtual Machine (PVM). - Do note that the primary focus of this release is native executability, - not the graphical notation - but we recognize its importance for - further releases. = + The goal of this effort is to build a = native BPMN2 runtime engine + (or better said implementing 'BPMN2 exectuable') leveraging th= e Process + Virtual Machine (PVM). + Do note that the primary focus of this release is native execu= tability, + not the graphical notation - but we recognize its importance f= or + further releases. - = + Users who are already familiar with jBPM will find that @@ -71,152 +71,166 @@ So in general, our main goal is to keep everything that was good abo= ut jBPM, and enhance it with a standards based process language. - = +
- = +
- = + JPDL vs BPMN 2.0 - = - - One of the first questions that might, rightfully, come to mind is why - BPMN2 is being implemented while there is jPDL. Both are languages - have as goal to define executable business processes. From a high-level - technical point of view, both languages are equivalent. The main - distinction is that BPMN2 is as vendor-neutral as you can have with - standards, while JPDL has always been tied to jBPM (although some might - argue that a vendor lock-in for an open-source process language such as - JPDL is less a lock-in than with closed-source products). - + + + One of the first questions that might, rightfully, come to min= d is why + BPMN2 is being implemented while there is jPDL. Both are langu= ages + have as goal to define executable business processes. From a h= igh-level + technical point of view, both languages are equivalent. The ma= in + distinction is that BPMN2 is as vendor-neutral as you can have= with + standards, while JPDL has always been tied to jBPM (although s= ome might + argue that a vendor lock-in for an open-source process languag= e such as + JPDL is less a lock-in than with closed-source products). + - Within jBPM, both language implementations are built on top of the jBPM - Process Virtual Machine (PVM). This means that both languages share a - common foundation (persistence, transactions, configuration, but also - basic process constructs, etc.). As a result, optimizations to the core - of jBPM often benefits both languages. Leveraging the PVM, the BPMN2 - implementation is built upon a foundation that has already proven - itself in the past and has a large end-user community. - + Within jBPM, both language implementations are built on top of= the jBPM + Process Virtual Machine (PVM). This means that both languages = share a + common foundation (persistence, transactions, configuration, b= ut also + basic process constructs, etc.). As a result, optimizations to= the core + of jBPM often benefits both languages. Leveraging the PVM, the= BPMN2 + implementation is built upon a foundation that has already pro= ven + itself in the past and has a large end-user community. + - When evaluating the languages and comparing them which each other howe= ver, - following points must be taken into consideration: - + When evaluating the languages and comparing them which each othe= r however, + following points must be taken into consideration: + BPMN2 is based on a standard accepted by the BPM industr= y. BPMN2 is implementation-unaware. The downside of this is= that - integrating with Java technology will always be easier with JPDL. = So, - from a Java developer's perspective JPDL is simpler and feels more - natural (some of the 'layers' of BPEL/WSDL are in BPMN as well). + integrating with Java technology will always be easier with = JPDL. So, + from a Java developer's perspective JPDL is simpler and feel= s more + natural (some of the 'layers' of BPEL/WSDL are in BPMN as we= ll). A focus of JPDL is XML readability. BPMN2 processes will= still be - readable to a certain level, but tooling or a more detailed knowle= dge - of the spec will definitely be required to achieve the same level = of - productivity. + readable to a certain level, but tooling or a more detailed = knowledge + of the spec will definitely be required to achieve the same = level of + productivity. Java developers who are super-fast in JPDL since they kn= ow the JPDL - language by heart, will find the use of tools sometimes bothersome= and - the language itself overly complicated. + language by heart, will find the use of tools sometimes both= ersome and + the language itself overly complicated. BPMN2 contains a large set of constructs described in the - specification. However, the "binding" of interfaces to code is left - open in the spec (comparable with XPDL), even if WDSL is often con= sidered the - default. This means that a process portability can be lost when po= rting - the process to an engine that doesn't support the same binding - mechanism. Calling Java classes for example is already going to be= such - a jBPM specific binding. + specification. However, the "binding" of interfaces to code = is left + open in the spec (comparable with XPDL), even if WDSL is oft= en considered the + default. This means that a process portability can be lost w= hen porting + the process to an engine that doesn't support the same bindi= ng + mechanism. Calling Java classes for example is already going= to be such + a jBPM specific binding. - + - It is natural to the political level of BPMN2 specification process to = go - rather slow. JPDL on the other hand will be able to incorporate changes - faster, integrate with new technologies when they are released and - evolve generally at a quicker pace compared to BPMN2. - = - Of course, since both are built on top of the same PVM, it is only - logical that additions to JPDL can be ported to BPMN2 as an extension - without much hassle. - - = + It is natural to the political level of BPMN2 specification pr= ocess to go + rather slow. JPDL on the other hand will be able to incorporat= e changes + faster, integrate with new technologies when they are released= and + evolve generally at a quicker pace compared to BPMN2. + + Of course, since both are built on top of the same PVM, it is = only + logical that additions to JPDL can be ported to BPMN2 as an ex= tension + without much hassle. + + + + When we deploy a BPMN 2.0 process, follows these rules: + + + When there is no id attribute on BPMN 2.0 process, d= eploy failed. + + + When there is only an id attribute on BPMN 2.0 proce= ss, using id attribute as process definition name. + + + When there is both id and name attributes on BPMN 2.= 0 process, using id as key, using name as name for process definition. + + +
- = +
- = + Bpmn 2.0 execution = - The BPMN2 specification defines a very rich language for modeling and - executing business processes. However, this also means that it is quite - hard to get an overview of what's possible with BPMN2. To simplify this - situation, we've decided to categorize the BPMN2 constructs into three - 'levels'. The separation itself is primarily based on the book 'BPMN - method and Style' by Bruce Silver (http://www.bpmnstyle.com/), the - training material of Dr. Jim Arlow - (http://www.slideshare.net/jimarlow/introductiontobpmn005), = - 'How much BPMN do you need' - (http://www.bpm-research.com/2008/03/03/how-much-bpmn-do-you-need= /), - and also our own experience. - - - We define three categories of BPMN2 constructs: - - Basic: constructs in th= is category are = - straight-forward and easy to grasp. Constructs in this category ca= n be used to = - model simple business processes. - Advanced: contains more= powerful or = - expressive constructs, but this comes with higher modeling and exe= cution semantics = - learning curve. The majority of business processes are implementab= le with constructs from this - and the previous category. - Complex: constructs in = this category are = - used in specific and/or rare cases, or their semantics are difficu= lt to understand. - + The BPMN2 specification defines a very rich language for model= ing and + executing business processes. However, this also means that it= is quite + hard to get an overview of what's possible with BPMN2. To simp= lify this + situation, we've decided to categorize the BPMN2 constructs in= to three + 'levels'. The separation itself is primarily based on the book= 'BPMN + method and Style' by Bruce Silver (http://www.bpmnstyle.com/), the + training material of Dr. Jim Arlow + (http://www.slideshare.net/jimarlow/introductiontobpmn005= ), + 'How much BPMN do you need' + (http://www.bpm-research.com/2008/03/03/how-much-bpmn-do= -you-need/), + and also our own experience. + + + We define three categories of BPMN2 constructs: + + Basic: constructs= in this category are + straight-forward and easy to grasp. Constructs in this categ= ory can be used to + model simple business processes. + Advanced: contain= s more powerful or + expressive constructs, but this comes with higher modeling a= nd execution semantics + learning curve. The majority of business processes are imple= mentable with constructs from this + and the previous category. + Complex: construc= ts in this category are + used in specific and/or rare cases, or their semantics are d= ifficult to understand. + - = -
= - = + + +
- = + Configuration - = + Enabling BPMN 2.0 in your application is extremely simple: just add = the following line to the jbpm.cfg.xml file. -<import resource=3D"jbpm.bpmn.cfg.xml" /> = +<import resource=3D"jbpm.bpmn.cfg.xml" /> This import will enable BPMN 2.0 process deployment by installing a = BPMN 2.0 deployer in the Process Engine. Do note that a Process Engine can cope with b= oth JPDL and BPMN 2.0 processes. This means that in your application, some processes can b= e JPDL and others can be BPMN 2.0. - = + Process definitions are distinguished by the= process engine based on the extension of the definition file. For BPMN 2.0, use the= *.bpmn.xml extension (where JPDL is having the *.jpdl.xml extension). - = +
- = +
- = + Examples - = + - The examples that are shipped with the distribution also contain exa= mples for every = + The examples that are shipped with the distribution also contain exa= mples for every construct that is discussed in the following sections. Look for exam= ple BPMN 2.0 processes and test cases in the org.jbpm.exa= mples.bpmn.* package . - = + See the userguide, chapter 2 (Installation), for a walktough on how = to import the examples. Look for the section 'Importing the Examples= '. - = +
- = +
- = + Process root element - = + - The root of an BPMN 2.0 XML process is the d= efinitions = + The root of an BPMN 2.0 XML process is the d= efinitions elements. As the name states, the subelements will contain the actua= l definitions of the business process(es). Every process child will be able to have an id (required) and @@ -227,36 +241,36 @@ <definitions id=3D"myProcesses" xmlns:xsi=3D"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=3D"http://schema.omg.org/spec/BPMN/2.0 BPMN20.xs= d" - xmlns=3D"http://schema.omg.org/spec/BPMN/2.0" = + xmlns=3D"http://schema.omg.org/spec/BPMN/2.0" typeLanguage=3D"http://www.w3.org/2001/XMLSchema" - expressionLanguage=3D"http://www.w3.org/1999/XPath" = + expressionLanguage=3D"http://www.w3.org/1999/XPath" targetNamespace=3D"http://jbpm.org/example/bpmn2"> = - <process id=3D"My business processs" name=3D"myBusines= sProcess"> = - = + <process id=3D"My business processs" name=3D"myBusines= sProcess"> + ... - = + </process> -<definitions> = +<definitions> If a name is defined for the process element, it is be used as key for that process (ie. starting a process can be done by calling exec= utionService.startProcessInstanceByKey("myBusinessProcess"). If no name is defined, the id will be used as key. So having only an= id defined, will allow - to start a process instance using that id. So basically, name and ke= y are of equivalent = + to start a process instance using that id. So basically, name and ke= y are of equivalent in usage, for example to search process definitions. Note that for a= key the same rules apply as with JPDL: whitespace and non alpha-numeric characters are replaced by an= underscore. - = +
- = +
- = + Basic constructs - = +
- = + Events - = + Together with activitites and gateways, events are used in practic= ally every business process. Events allow process modelers to describe business processes in a = very natural way, such as @@ -267,70 +281,70 @@ always work in a very event-driven way. People are not hard-coded = sequential creatures, but they tend to react on things that happen in their environment = (ie. events). In the BPMN specification, a great number of event types are descr= ibed, to cover the - range of possible things that might occur in context of a business= . = + range of possible things that might occur in context of a business. - = -
= - = + +
+
- = + Event: None start event - = + A start event indicates the start of process (or a subprocess). Gr= aphically, it is visualized - as a circle with (possibly) a small icon inside. The icon specifie= s the actual type of event = + as a circle with (possibly) a small icon inside. The icon specifie= s the actual type of event that will trigger the process instance creation. - = + The 'none start event' is drawn as a circle without an icon inside= , which means that the trigger is unknown or unspecified. The start activity of JPDL basi= cally has the same - semantics. Process instances whose process definition has a 'none = start event' are = + semantics. Process instances whose process definition has a 'none = start event' are created using the typical API calls on the executionService. - = + A none start event is defined as follows. An id is required, a na= me is optional. -<startEvent id=3D"start" name=3D"myStart" /> = = +<startEvent id=3D"start" name=3D"myStart" /> - = +
=
= - Event: None end event + Event: None end event = - - An end event indicates the end of an execution path in a process - instance. Graphically, - it is visualized as a circle with a thick border with (possibly) a - small icon inside. - The icon specifies the type of signal that is thrown when the end is - reached. + + An end event indicates the end of an execution path in a pro= cess + instance. Graphically, + it is visualized as a circle with a thick border with (possi= bly) a + small icon inside. + The icon specifies the type of signal that is thrown when th= e end is + reached. - = + The 'none end event' is drawn as a circle with thick border with n= o icon inside, which means that no signal is thrown when the execution reaches th= e event. The end activity in JPDL has the same semantics as the none end ev= ent. - = + A none end event is defined as follows. An id is required, a name = is optional. -<endEvent id=3D"end" name=3D"myEnd" /> = = +<endEvent id=3D"end" name=3D"myEnd" /> - = + The following example shows a process with only a none start and= end event: - = + - The corresponding executable XML for this process looks like thi= s (omitting the = + The corresponding executable XML for this process looks like thi= s (omitting the definitions root element for clarity) <process id=3D"noneStartEndEvent" name=3D"BPMN2 Exampl= e none start and end event"> @@ -342,43 +356,43 @@ = <endEvent id=3D"end" name=3D"= ;End" /> = - </process> = + </process> - = + - A process instances can now be created by calling the = + A process instances can now be created by calling the startProcessInstanceXXX opera= tions. ProcessInstance processInstance =3D executionService.startProcessInstanceB= yKey("noneStartEndEvent"); - = +
- = +
- = + Event: Terminate end event - = + - The difference between a 'terminate' and a 'none' end event = + The difference between a 'terminate' and a 'none' end event lies in the fact how a path of execution is treated (or a 'token= ' in BPMN 2.0 terminology). - The 'terminate' end event will end the complete process instance= , whereas the 'none' = + The 'terminate' end event will end the complete process instance= , whereas the 'none' end event will only end the current path of execution. They both= don't throw anything when the end event is reached. - = + A terminate end event is defined as follows. An id is required, = a name is optional. <endEvent id=3D"terminateEnd" name=3D"myTerminateEnd&quo= t;> <terminateEventDefinition/> -</endEvent> = +</endEvent> - = + - A terminate end event is depicted as an end event (circle with t= hick border), = + A terminate end event is depicted as an end event (circle with t= hick border), with a full circle as icon inside. In the following example, com= pleting the 'task1' will end the process instance, while completing the 'task2' will= only end the path of execution which enters the end event, leaving the task1 open. @@ -386,25 +400,25 @@ See the examples shipped with the jBPM distribution for the unit= test and XML counterpart of this business process. - = +
- = +
- = + Sequence Flow - = + A sequence flow is the connection between events, activities and g= ateways shown as a solid line with an arrow in a BPMN diagram (JPDL equivalent is the= transition). - Each sequence flow has exactly one source<= /emphasis> and exactly one = - target reference, that contains= the id = + Each sequence flow has exactly one source<= /emphasis> and exactly one + target reference, that contains= the id of an activity, event or gateway. -<sequenceFlow id=3D"myFlow" name=3D"My Flow" = +<sequenceFlow id=3D"myFlow" name=3D"My Flow" sourceRef=3D"sourceId" targetRef=3D"targetId" = /> - = + An important difference with JPDL is the behaviour of multiple out= going sequence flows. In JPDL, only one transition is selected as outgoing transition, u= nless the activity @@ -417,23 +431,23 @@ At runtime, only when the condition evaluates to true, that sequenc= e flow will be taken. - = + To put a condition on a sequence flow, add a conditionExpression element to the sequence flow. Conditions are to be put= between ${}. <sequenceFlow id=3D....> - <conditionExpression xsi:type=3D"tFormal= Expression">${amount >=3D 500}</conditionExpression> = -</sequenceFlow> = + <conditionExpression xsi:type=3D"tFormal= Expression">${amount >=3D 500}</conditionExpression> +</sequenceFlow> Note that is currently is necessary to add the xsi:type=3D"tFormalExpression" to the conditionExpression. A conditional sequence flow is vis= ualized as a mini diamond - shape at the beginning of the sequence flow. Keep in mind that con= ditions always can be defined = + shape at the beginning of the sequence flow. Keep in mind that con= ditions always can be defined on sequence flow, but some constructs will not interprete them (eg= . parallel gateway). - = + Activities (such as the user task) and gateways (such as the excl= usive gateway) can have a default sequence flow. This default sequence flow is taken only wh= en all the other outgoing @@ -443,28 +457,28 @@ The default sequence flow is specified by filling in the 'default' attribute of the activity or gateway. - = + Also note that an expression on a default sequence flow is ignore= d. - = +
- = +
- = + Gateways - = + - A gateway in BPMN is used to control the flow through the process.= More specifically, = - when a token (the BPMN 2.0 conceptual notion of an execution) arri= ves in a gateway, it can be merged = + A gateway in BPMN is used to control the flow through the process.= More specifically, + when a token (the BPMN 2.0 conceptual notion of an execution) arri= ves in a gateway, it can be merged or split depending on the gateway type. - = + - Gateways are depicted as a diamond shape, with an icon inside spec= ifying the type = + Gateways are depicted as a diamond shape, with an icon inside spec= ifying the type (exclusive, inclusive, etc.). - = + On every gateway type, the attribute gatew= ayDirection can be set. following values are possible: @@ -489,38 +503,38 @@ Take for example the following example: a parallel gateway that ha= s as gatewayDirection 'converging', will have a join behaviour. -<parallelGateway id=3D"myJoin" name=3D"My synchronizing = join" gatewayDirection=3D"converging" /> = +<parallelGateway id=3D"myJoin" name=3D"My synchronizing = join" gatewayDirection=3D"converging" /> - Note: the 'gatewayDirection' at= tribute is optional according = + Note: the 'gatewayDirection' at= tribute is optional according to the specification. This means that we cannot rely on this attri= bute at runtime to know which type of behaviour a certain gateway has (for example fo= r a parallel gateway if - we have joining of forking behaviour). However, the 'gatewayDirect= ion' attribute is used at parsing = - time as a constraint check for the incoming/outgoing sequence flow= . So using this = + we have joining of forking behaviour). However, the 'gatewayDirect= ion' attribute is used at parsing + time as a constraint check for the incoming/outgoing sequence flow= . So using this attribute will lower the chance on errors when referencing sequenc= e flow, but is not required. - = +
- = +
- = + Gateway: Exclusive Gateway - = + An exclusive gateway represents an exclusi= ve decision in the process. Exactly one outgoing sequence flow will be taken, = depending on the conditions defined on the sequence flow. - = + - The corresponding JPDL construct with the same semantics is the = - decision activity. The full tec= hnical name of the = + The corresponding JPDL construct with the same semantics is the + decision activity. The full tec= hnical name of the exclusive gateway is the 'exclusive data-b= ased gateway', but it is also often called the XOR Gatewa= y. The XOR gateway is depicted as a diamond with a 'X' icon inside. A= n empty diamond without a gateway also signifies an exclusive gateway. - = + The following diagram shows the usage of an exclusive gateway: dep= ending on the value of the amount variable, one of the three outgoing sequence flow out of th= e exclusive gateway @@ -538,47 +552,47 @@ = <sequenceFlow id=3D"flow1" name=3D"fromStartToExclusi= veGateway" sourceRef=3D"start" targetRef=3D"decideBasedOnAmountG= ateway" /> - = + <exclusiveGateway id=3D"decideBasedOnAm= ountGateway" name=3D"decideBasedOnAmount" /> - = + <sequenceFlow id=3D"flow2" name=3D"fromGatewayToEndNo= tEnough" sourceRef=3D"decideBasedOnAmountGateway" targetRef=3D"= ;endNotEnough"> <conditionExpression xsi:type=3D"tFo= rmalExpression"> ${amount < 100} </conditionExpression> </sequenceFlow> - = + <sequenceFlow id=3D"flow3" name=3D"fromGatewayToEnEno= ugh" sourceRef=3D"decideBasedOnAmountGateway" targetRef=3D"= ;endEnough"> <conditionExpression xsi:type=3D"tFo= rmalExpression"> ${amount <=3D 500 && amount >=3D 100} </conditionExpression> </sequenceFlow> - = + <sequenceFlow id=3D"flow4" name=3D"fromGatewayToMoreT= hanEnough" sourceRef=3D"decideBasedOnAmountGateway" targetRef=3D"= ;endMoreThanEnough"> <conditionExpression xsi:type=3D"tFo= rmalExpression"> ${amount > 500} </conditionExpression> - </sequenceFlow> = + </sequenceFlow> = <endEvent id=3D"endNotEnough" name=3D"not enough"= ; /> - = + <endEvent id=3D"endEnough" name=3D"enough" /> - = + <endEvent id=3D"endMoreThanEnough" name=3D"more than = enough" /> = - </process> = + </process> This process needs a variable such that the expression can be eval= uated at runtime. Variables can be provided when starting the process instance (simi= lar to JPDL): Map<String, Object> vars =3D new HashMap<String, Object>(); vars.put("amount", amount); -ProcessInstance processInstance =3D executionService.startProcessInstanceB= yKey("exclusiveGateway", vars); = +ProcessInstance processInstance =3D executionService.startProcessInstanceB= yKey("exclusiveGateway", vars); - = + The exclusive gateway requires that all outgoing sequence flow hav= e conditions defined on them. An exception to this rule is the default sequence flow. @@ -587,161 +601,161 @@ when the conditions on the other outgoing sequence flow all evalua= te to false. <exclusiveGateway id=3D"decision" name=3D"decideBasedOnA= mountAndBankType" default=3D"myFlow"= /> - = + <sequenceFlow id=3D"myFlow" name=3D"fromGatewayToStandar= d" sourceRef=3D"decision" targetRef=3D"standard"> -</sequenceFlow> = +</sequenceFlow> - An exclusive gateway can have both convering and diverging functio= nality. The logic is = + An exclusive gateway can have both convering and diverging functio= nality. The logic is easy to grasp: for every execution that arrives at the gateway, on= e outgoing sequence flow is selected to continue the flow. The following diagram is c= ompletely legal in - BPMN 2.0 (omitting names and conditions for clarity). = + BPMN 2.0 (omitting names and conditions for clarity). - = +
- = +
- = + Gateway: Parallel Gateway - = + A parallel gateway is used to split or synchronize the respectivel= y incoming or outgoing sequence flow. A parallel gateway with one incoming sequence flow and more th= an one outgoing sequence - flow is called a 'parallel split or an = + flow is called a 'parallel split or an 'AND-split'. All outgoing s= equence flow are going to be taken in parallel. Note: as defined= by the specification, conditions on the outgoing sequence flow are ignored. A parallel gateway with multiple incoming sequence flow and on= e outgoing sequence flow - is called a 'parallel join'= or an = + is called a 'parallel join'= or an AND-join. All incoming sequ= ence flow need to arrive in this parallel joing before the outgoing sequence flow is ta= ken. A parallel gateway is defined as follows: -<parallelGateway id=3D"myParallelGateway" name=3D"My Par= allel Gateway" /> = +<parallelGateway id=3D"myParallelGateway" name=3D"My Par= allel Gateway" /> - Note that the 'gatewayDirection' attribute can be used to catch mo= deling errors at parsing = + Note that the 'gatewayDirection' attribute can be used to catch mo= deling errors at parsing time (see above). - = + The following diagram shows how a parallel gateway can be used. Af= ter process start, both the 'prepare shipment' and 'bill customer' user tasks will be= active. - The parallel gateway is depicted as a diamond shape with a plus ic= on inside, both for the = + The parallel gateway is depicted as a diamond shape with a plus ic= on inside, both for the splitting and joining behaviour. The XML counterpart of this diagram looks as follows: <process id=3D"parallelGateway" name=3D"BPMN2 example = parallel gatewar"> - = + <startEvent id=3D"Start" /> = <sequenceFlow id=3D"flow1" name=3D"fromStartToSplit&= quot; sourceRef=3D"Start" targetRef=3D"parallelGatewaySplit" /> = - <parallelGateway id=3D"parallelGateway= Split" name=3D"Split" = + <parallelGateway id=3D"parallelGateway= Split" name=3D"Split" gatewayDirection=3D"diverging"/> = <sequenceFlow id=3D"flow2a" name=3D"Leg 1" sourceRef=3D"parallelGatewaySplit" targetRef=3D"prepareShipment" /> - = - <userTask id=3D"prepareShipment" name=3D"Prepare shi= pment" = + + <userTask id=3D"prepareShipment" name=3D"Prepare shi= pment" implementation=3D"other" /> - = + <sequenceFlow id=3D"flow2b" name=3D"fromPrepareShipm= entToJoin" sourceRef=3D"prepareShipment" targetRef=3D"parallelGatewayJoin" /> - = - <sequenceFlow id=3D"flow3a" name=3D"Leg 2" = + + <sequenceFlow id=3D"flow3a" name=3D"Leg 2" sourceRef=3D"parallelGatewaySplit" targetRef=3D"billCustomer" /> - = - <userTask id=3D"billCustomer" name=3D"Bill customer&= quot; = + + <userTask id=3D"billCustomer" name=3D"Bill customer&= quot; implementation=3D"other" /> - = + <sequenceFlow id=3D"flow3b" name=3D"fromLeg2ToJoin&q= uot; sourceRef=3D"billCustomer" targetRef=3D"parallelGatewayJoin" /> = - <parallelGateway id=3D"parallelGateway= Join" name=3D"Join" = + <parallelGateway id=3D"parallelGateway= Join" name=3D"Join" gatewayDirection=3D"converging"/> - = - <sequenceFlow id=3D"flow4" = + + <sequenceFlow id=3D"flow4" sourceRef=3D"parallelGatewayJoin" targetRef=3D"End"> </sequenceFlow> = <endEvent id=3D"End" name=3D"End" /> - = + </process> - A parallel gateway (as is the case for any gateway) can have both = splitting and = + A parallel gateway (as is the case for any gateway) can have both = splitting and merging behaviour. The following diagram is completely legal BPMN = 2.0. After process start, - both task A and B will be active. When both A en B are completed, = tasks C,D and E will be = - active. = + both task A and B will be active. When both A en B are completed, = tasks C,D and E will be + active. - = +
- = +
- = + Gateway: Inclusive Gateway - = + An inclusive gateway - also called an OR-g= ateway - is used - to 'conditionally' split or merge sequence flow. It basically beha= ves as a parallel = + to 'conditionally' split or merge sequence flow. It basically beha= ves as a parallel gateway, but it also takes in account conditions on the outgoing s= equence flow (split behaviour) and calculates if there are executions left that could reach the g= ateway (merge behaviour). - = + The inclusive gateway is depicted as a typical gateway shape with = a circle inside (referring to 'OR' semantics). Unlike the exclusive gateway, all condition expressions are evalua= ted (diverging or 'split' behaviour). - For every expression that evaluates to true, a new child execution= is created. = + For every expression that evaluates to true, a new child execution= is created. Sequence flow without a condition will always be taken (ie. a chil= d execution will always be - created in that case). = + created in that case). - = + A converging inclusive gateway ('merge' behaviour) has a somewhat = more difficult execution logic. - When an execution (Token in BPMN 2.0 terminology) arrives at the m= erging inclusive gateway, = - the following is checked (quoting the specification literally): = - = + When an execution (Token in BPMN 2.0 terminology) arrives at the m= erging inclusive gateway, + the following is checked (quoting the specification literally): + -For each empty incoming sequence flow, there is no = -Token in the graph anywhere upstream of this sequence flow, i.e., there is= no directed path = -(formed by Sequence Flow) from a Token to this sequence flow unless = -a) the path visits the inclusive gateway or = +For each empty incoming sequence flow, there is no +Token in the graph anywhere upstream of this sequence flow, i.e., there is= no directed path +(formed by Sequence Flow) from a Token to this sequence flow unless +a) the path visits the inclusive gateway or b) the path visits a node that has a directed path to a non-empty incoming sequence flow of the inclusive gateway. " - = + In more simple words: when an execution arrives at the gateway, al= l active execution are checked if they can reach the inclusive gateway, by only taking in= account the sequence flow (note: conditions are not evaluated!). When the inclusive gateway = is used, it is usally used in a pair of splitting/merging inclusive gateways. In those c= ases, the execution - behaviour is easy enough to grasph by just looking at the model. = - = + behaviour is easy enough to grasph by just looking at the model. + - = - = - Of course, it is not hard to imagine situations where the executio= ns are split and merged = + + + Of course, it is not hard to imagine situations where the executio= ns are split and merged in complex combinations using a variety of constructs including th= e inclusive gateway. In those cases, it could very well be that the actual execution be= haviour might not be what the modelers' expects. So be careful when using the inclusive gate= way and keep in mind that it is often the best practice to use inclusive gateways just = in pairs. - = + The following diagram shows how the inclusive gateway can be used. (example taken from "BPMN method and style" by Bruce Sil= ver) @@ -753,26 +767,26 @@ "Large deposit" task will be active. - Cash more than 10000 and a foreign ba= nk: Both the = + Cash more than 10000 and a foreign ba= nk: Both the "Large deposit" and "Foreign deposit" tas= k will be active. - Cash lower than 10000 and a foreign b= ank: Only the = + Cash lower than 10000 and a foreign b= ank: Only the "Foreign deposit" task will be active. - Cash lower than 10000 and not a forei= gn bank: In this = + Cash lower than 10000 and not a forei= gn bank: In this case, both expressions evaluate to false. The default sequenc= e flow will now be chosen. In this example, this means that the "Standard deposit&q= uot; task is active. No matter how many tasks are active after going through the inclus= ive gateway, the converging inclusive gateway on the right will wait until all outgoing sequen= ce flow of the inclusive - gateway on the left have reached the merging gateway (sometimes on= ly one, sometimes two). Take a look at = - org.jbpm.examples.bpmn.gateway.inclusive.I= nclusiveGatewayTest = + gateway on the left have reached the merging gateway (sometimes on= ly one, sometimes two). Take a look at + org.jbpm.examples.bpmn.gateway.inclusive.I= nclusiveGatewayTest to see how this example reflects in a unit test. - = + The XML version of the example above looks as follows: @@ -781,33 +795,33 @@ <startEvent id=3D"start" /> = <sequenceFlow id=3D"flow1" sourceRef=3D"start" t= argetRef=3D"inclusiveGatewaySplit" /> - = + <inclusiveGateway id=3D"inclusiveGatewa= ySplit" default=3D"flow3"/> - = + <sequenceFlow id=3D"flow2" sourceRef=3D"inclusiveGatewaySplit" targetRef=3D"largeDe= posit"> <conditionExpression xsi:type=3D"tFormalExpression">= ${cash > 10000}</conditionExpression> </sequenceFlow> - = + <sequenceFlow id=3D"flow3" sourceRef=3D"inclusiveGatewaySplit" targetRef=3D"standar= dDeposit" /> - = + <sequenceFlow id=3D"flow4" sourceRef=3D"inclusiveGatewaySplit" targetRef=3D"foreign= Deposit"> <conditionExpression xsi:type=3D"tFormalExpression">= ${bank =3D=3D 'foreign'}</conditionExpression> - </sequenceFlow> = - = + </sequenceFlow> + <userTask id=3D"largeDeposit" name=3D"Large deposit&q= uot; /> - = + <sequenceFlow id=3D"flow5" sourceRef=3D"largeDeposit&= quot; targetRef=3D"inclusiveGatewayMerge"= /> - = + <userTask id=3D"standardDeposit" name=3D"Standard dep= osit" /> - = + <sequenceFlow id=3D"flow6" sourceRef=3D"standardDepos= it" targetRef=3D"inclusiveGatewayMerge&qu= ot; /> - = + <userTask id=3D"foreignDeposit" name=3D"Foreign depos= it" /> - = + <sequenceFlow id=3D"flow7" sourceRef=3D"foreignDeposi= t" targetRef=3D"inclusiveGatewayMerge&quo= t; /> - = + <inclusiveGateway id=3D"inclusiveGatewa= yMerge" /> - = + <sequenceFlow id=3D"flow8" sourceRef=3D"inclusiveGat= ewayMerge" targetRef=3D"theEnd" /> = <endEvent id=3D"theEnd" /> @@ -815,7 +829,7 @@ </process> - = + As with any gateway type, the inclusive gateway type can have both= merging and splitting behaviour. In that case, the inclusive gateway will first wait unt= il all executions @@ -823,74 +837,74 @@ that evauluates to true (or doesn't have a condition). - = -
= - = + + +
= Tasks - = + A task represents work that needs to be done by an external entity, such as a human actor or an automated service. - = + It's important to note that the BPMN semantics of a 'task' differ = from the JPDL semantics. - In JPDL, the concept 'task' is always used in the context of a hum= an actor doing some = + In JPDL, the concept 'task' is always used in the context of a hum= an actor doing some type of work. When the process engine encounters a task in JPDL, i= t will create a task in some human actor's task list and it will behave as a wait state. In BPMN 2.0 = however, there are several task types, some indicating a wait state (eg. the User Task and some indicating an automatic activity (eg. the Service Task). So take good care not to confuse the meaning of the task concept w= hen switching languages. - = + Tasks are depicted by a rounded rectangle, typically containing a = text inside. The type - of the task (user task, service task, script task, etc.) is shown = as a little icon on the left top = - corner of the rectangle. Depending on the task type, the engine wi= ll execute different = + of the task (user task, service task, script task, etc.) is shown = as a little icon on the left top + corner of the rectangle. Depending on the task type, the engine wi= ll execute different functionality. - = +
- = +
- = + Task: User Task - = + A User task is the typical 'hum= an task' that is found in practically every workflow or BPM software out there. When proc= ess execution reaches such a user task, a new human task is created in task list for a g= iven user. - = - = + + The main difference with a manual tas= k (which also signifies - work for a human actor) is that the task is known to the process e= ngine. The engine can = - track the completion, assignee, time, etc which is not the case fo= r a manual task. = + work for a human actor) is that the task is known to the process e= ngine. The engine can + track the completion, assignee, time, etc which is not the case fo= r a manual task. - = + A user task is depicted as a rounded rectangle with a small user i= con in the top left corner. A user task is defined as follows in the BPMN 2.0 XML: -<userTask id=3D"myTask" name=3D"My task" /> = - = +<userTask id=3D"myTask" name=3D"My task" /> + According to the specification, multiple implementations are possi= ble (Webservice, WS-humantask, etc.), as stated by using the implementation attribute. Currently, only the standard jBPM task mechanism is available, so = there is no point (yet) in defining the 'implementation' attribute. - = + - The BPMN 2.0 specification contains quite a few ways of assigning = user tasks to user(s), = + The BPMN 2.0 specification contains quite a few ways of assigning = user tasks to user(s), group(s), role(s), etc. The current BPMN 2.0 jBPM implementation a= llows to assign tasks using a resourceAssignmentExpression,= combined with the humanPerformer or PotentialOwner<= /emphasis> construct. It is to be expected that this area will evolve future releases. - = + A potentialOwner is used when y= ou want to make a certain user, group, role, etc. a candidate for a certain task. @@ -901,36 +915,36 @@ Currently, only defining this resource is enough (since it is a re= quired attribute by the spec), but this will be enhanced in a later release (eg. resources can ha= ve runtime parameters). -<resource id=3D"manager" name=3D"manager" /> = +<resource id=3D"manager" name=3D"manager" /> = <process ...> = -... = - = +... + <userTask id=3D"myTask" name=3D"My task"> <potentialOwner resourceRef=3D"manager" jbpm:type=3D"g= roup"> <resourceAssignmentExpression> <formalExpression>management</formalExpression> </resourceAssignmentExpression> </potentialOwner> -</userTask> = +</userTask> - Note that we are using a specific extension here = + Note that we are using a specific extension here (jbpm:type=3D"group")= , to define this is a group assignment. - If this attribute is removed, the group semantics will be used as = default (which would be = + If this attribute is removed, the group semantics will be used as = default (which would be ok in this example). Now suppose that Peter and Mary are a member of the management gro= up (here using the default identity service): identityService.createGroup("management"); - = + identityService.createUser("peter", "Peter", "Pan"); identityService.createMembership("peter", "managem= ent"); - = + identityService.createUser("mary", "Mary", "Littlelamb"); -identityService.createMembership("mary", "manageme= nt"); = +identityService.createMembership("mary", "manageme= nt"); - Then both peter and mary can look in their task list for this task= (code snippet from the = + Then both peter and mary can look in their task list for this task= (code snippet from the example unit test): // Peter and Mary are both part of management, so they both should see the= task @@ -938,14 +952,14 @@ assertEquals(1, tasks.size()); tasks =3D taskService.findGroupTasks("mary&q= uot;); assertEquals(1, tasks.size()); - = + // Mary claims the task Task task =3D tasks.get(0); taskService.takeTask(task.getId(), "mary"); assertNull(taskService.createTaskQuery().candidate("peter").uniq= ueResult()); - = + taskService.completeTask(task.getId()); -assertProcessInstanceEnded(processInstance); = +assertProcessInstanceEnded(processInstance); When the assignment should be done to a ca= ndidate user, just use the jbpm:type=3D"user"= attribute. @@ -956,47 +970,47 @@ <formalExpression>peter</formalExpression> </resourceAssignmentExpression> </potentialOwner> -</userTask> = +</userTask> In this example, peter will be able to find the task since he's a = candidate user for the task. -List<Task> tasks =3D taskService.createTaskQuery().candidate("p= eter").list(); = +List<Task> tasks =3D taskService.createTaskQuery().candidate("p= eter").list();
- = + A human performer is used when yo= u want to assign a task directly to a certain user, group, role, etc. The way to do this loo= ks very much like that of the potential owner. -<resource id=3D"employee" name=3D"employee" /> = +<resource id=3D"employee" name=3D"employee" /> = <process ...> = -... = - = +... + <userTask id=3D"myTask" name=3D"My User task"> <humanPerformer resourceRef=3D"employee"><= /emphasis> <resourceAssignmentExpression> <formalExpression>mary</formalExpression> </resourceAssignmentExpression> </humanPerformer> -</userTask> = +</userTask> In this example, the task will be directly assigned to Mary. She can= now find the task in her task list: -List<Task> tasks =3D taskService.findPersonalTasks("mary")= ; = +List<Task> tasks =3D taskService.findPersonalTasks("mary"); - = - = + + - = + - Since the task assignment is done through the use of a = + Since the task assignment is done through the use of a formalExpression, it's also possi= ble to define expressions - that are evaluated at runtime. The expressions itself need to be put= inside a = + that are evaluated at runtime. The expressions itself need to be put= inside a ${}, as usual in jBPM. For example, if a process variable 'user' is defined, then it can b= e used inside an expression. More complex expressions are of course possible. @@ -1007,33 +1021,33 @@ <formalExpression>${user}</formalEx= pression> </resourceAssignmentExpression> </humanPerformer> -</userTask> = +</userTask> Note that it is not needed to use the 'jbpm:type' on a humanPerforme= r element, since only - direct user assignments can be done. If a task needs to be assigned = to a role or group, = + direct user assignments can be done. If a task needs to be assigned = to a role or group, use the potentialOwner with a group type (when you assign a task to = a group, all members - of that group will always be candidate users for that group - hence = the usage of = + of that group will always be candidate users for that group - hence = the usage of potentialOwner). - = +
- = + Task: Java Service Task - = + - A Service Task is an automatic = activity that calls some = + A Service Task is an automatic = activity that calls some sort of service, such as a web service, Java service, etc. Current= ly, only Java service - invocations are supported by the jBPM engine, but Web service invo= cations are planned = + invocations are supported by the jBPM engine, but Web service invo= cations are planned for a future release. - = + Defining a service task requires quite a few lines of XML (the BPE= L influence is certainly visible here). Of course, in the near future, we expect that tooli= ng will simplify this area a lot. A service task is defined as follows: -<serviceTask id=3D"MyServiceTask" name=3D"My service tas= k" = +<serviceTask id=3D"MyServiceTask" name=3D"My service tas= k" implementation=3D"Other" operationRef=3D"myOperation"= ; /> The service task has a required id and an optional @@ -1042,12 +1056,12 @@ are WebService, Other or Unspecified. Since we've only implemented= the Java invocation, only the Other choice will do s= omething useful for the moment. - = + - The service task will invoke a certain operation that is reference= d by the = - operationRef attribute using th= e id of an = - operation. Such an operation is= part of an = - interface as shown below. Every= operation has = + The service task will invoke a certain operation that is reference= d by the + operationRef attribute using th= e id of an + operation. Such an operation is= part of an + interface as shown below. Every= operation has at least one input message and = at most one output message. @@ -1057,7 +1071,7 @@ <inMessageRef>inputMessage</inMessageRef> <outMessageRef>outputMessage</outMessageRef> </bpmn:operation> -</interface> = +</interface> For a Java service, the name of the interf= ace is used to specificy the fully qualified classname of the Java class. The = @@ -1065,50 +1079,50 @@ that must be called. The input/output message that represent the p= arameters/return value of the Java method are defined as follows: -<message id=3D"inputMessage" name=3D"input message"= structureRef=3D"myItemDefinition1" /> = +<message id=3D"inputMessage" name=3D"input message"= structureRef=3D"myItemDefinition1" /> Several elements in BPMN are so-called 'item-aware', including thi= s message construct. This means that they are involved in storing or reading items duri= ng process execution. - The data structure to hold these elements is specified using a ref= erence to an = - ItemDefinition. In this context= , the message specifies = - its data structure by referencing an Itemdefinition in the = + The data structure to hold these elements is specified using a ref= erence to an + ItemDefinition. In this context= , the message specifies + its data structure by referencing an Itemdefinition in the structureRef attribute. - = + <itemDefinition id=3D"myItemDefinition1" > <jbpm:arg> <jbpm:object expr=3D"#{var1}" /> </jbpm:arg> </itemDefinition> - = + <itemDefinition id=3D"myItemDefinition2"> <jbpm:var name=3D"returnVar" /> </itemDefinition> - = + Do note that this is not fully standard BPMN 2.0 as by the specifi= cation (hence the 'jbpm' prefix). In fact, according to the specification, the ItemDefinition should= n't contain more than a data structure definition. The actual mapping between input= paramaters, with a ceratin data structure, is done in the ioSpecifica= tion section of the serviceTask. However, the current jBPM BPMN 2.0 implementat= ion hasn't implemented - that construct yet. So, this means that the current usage as descr= ibed above, will probably = + that construct yet. So, this means that the current usage as descr= ibed above, will probably change in the near future. - = + Important note: Interfaces, ItemDefinition= s and messages are defined outside a <process>. See the example ServiceTaskTest for a concrete process and unit test. - = - = -
= - = + + + +
- = + Task: Script Task - = + - A script task is a an automatic activity upon which the process en= gine will execute = + A script task is a an automatic activity upon which the process en= gine will execute a script when the task is reached. The script task is used as foll= ows: <scriptTask id=3D"scriptTask" name=3D"Script Task" = scriptLanguage=3D"bsh"> @@ -1117,11 +1131,11 @@ System.out.println(input[i] + " x 2 =3D " + (input[i]*2)); }]]> </script> -</scriptTask> = +</scriptTask> The script task, besides the required id and the optional name, allows for specifying a <= emphasis role=3D"bold"> - scriptLanguage and a script. = + scriptLanguage and a script. Since we're using JSR-223 ('Scripting for the Java platform'), cha= nging the script language involves changing the scriptLanguage attribute to the JSR-223 compliant name @@ -1129,17 +1143,17 @@ The XML above is visualized as follows (adding a none start and en= d event). - = + - = + As shown in the example, process variables can be used inside the = scripts. We can now start a process instance for this example process, while also supplying = some random input variables: Map<String, Object> variables =3D new HashMap<String, Object>(= ); Integer[] values =3D { 11, 23, 56, 980, 67543, 8762524 }; -variables.put("input", values); = -executionService.startProcessInstanceBykey("scriptTaskExample", = variables); = +variables.put("input", values); +executionService.startProcessInstanceBykey("scriptTaskExample", = variables); In the output console, we can now see the script being executed: @@ -1148,58 +1162,58 @@ 56 x 2 =3D 112 980 x 2 =3D 1960 67543 x 2 =3D 135086 -8762524 x 2 =3D 17525048 = +8762524 x 2 =3D 17525048 - = +
- = +
- = + Task: Manual task - = + - A manual task is a task that is performed by an external actor, b= ut without the aid of = + A manual task is a task that is performed by an external actor, b= ut without the aid of a BPM system or a service that is invoked. In the real world, exa= mples are plenty: - the installation of telephone system, sending of a letter using r= egular mail, calling = + the installation of telephone system, sending of a letter using r= egular mail, calling a customer by phone, etc. -<manualTask id=3D"myManualTask" name=3D"Call customer&qu= ot; /> = +<manualTask id=3D"myManualTask" name=3D"Call customer&qu= ot; /> - = + The purpose of the manual task is more documentation/modeling-wise= , as it has no meaning for execution on a process engine. As such, the process engine will si= mply pass through a manual task when it encounters one. - = +
- = +
- = + Task: Java Receive task - = + - A receive task is a task that w= aits for the arrival of = + A receive task is a task that w= aits for the arrival of an external message. Besides the obvious use case involving webser= vices, the specification - is liberal in what to do in other environments. The web service us= e case is not yet = + is liberal in what to do in other environments. The web service us= e case is not yet implemented, but the receive task can already be used in a Java en= vironment. - = + The receive task is depicted as a rounded rectangle (=3D task shap= e) with a little enveloppe in the left top corner. - = + In a Java environment, the receive task without any other attribut= e filled in besides an id and (optionally) a name, behaves as a wait state. To introdu= ce a wait state in your business process, just add the following line: -<receiveTask id=3D"receiveTask" name=3D"wait" />= = +<receiveTask id=3D"receiveTask" name=3D"wait" /> Process execution will wait in such a receive task. The process ca= n then be continued using the familiar jBPM signal methods. Note that @@ -1207,29 +1221,29 @@ meaning in BPMN 2.0. Execution execution =3D processInstance.findActiveExecutionIn("receiv= eTask"); -executionService.signalExecutionById(execution.getId()); = +executionService.signalExecutionById(execution.getId()); - = +
- = + - = +
- = + Advanced constructs - = +
- = + Embedded sub-process - = + - Subprocesses are in the first place a way of making a process "hie= rarchical", meaning that = - a modeller can create several 'levels' of detail. The top level vi= ew then explains the = - high-level way of doing things, while the lowest level focusses on= the nitty gritty = + Subprocesses are in the first place a way of making a process "hie= rarchical", meaning that + a modeller can create several 'levels' of detail. The top level vi= ew then explains the + high-level way of doing things, while the lowest level focusses on= the nitty gritty details. - = + Take for example the following diagram. In this model, only the hi= gh level steps are shown. The actual implementation of the "Check credit" step is = hidden behind a @@ -1237,13 +1251,13 @@ of detail to discuss business processes with end-users. - = + The second major use case for sub-processes is that the sub-proces= s "container" - acts as a scope for events. When an event is fired from within the= sub-process, the catch = + acts as a scope for events. When an event is fired from within the= sub-process, the catch events on the boundary of the sub-process will be the first to rec= eive this event. - = + A sub-process that is defined within a top-level process is called= an embeddable sub-process. All process data that is availa= ble in the parent @@ -1259,11 +1273,11 @@ <receiveTask name=3D"Receive order" id=3D"receiveOrd= er" /> <sequenceFlow id=3D"flow2" sourceRef=3D"receiveOrder= " targetRef=3D"checkCreditSubProcess" /> <subProcess id=3D"checkCreditSubProces= s" name=3D"Credit check"> - = + ... = </subProcess> - = + <sequenceFlow id=3D"flow9" sourceRef=3D"checkCreditS= ubProcess" targetRef=3D"theEnd" /> <endEvent id=3D"theEnd" /> = @@ -1273,7 +1287,7 @@ a top-level process (hence the three "..." within the X= ML example above. Sub-processes are only allowed to have a none start eve= nt. - = + Conceptually an embedded sub-process works as follows: when an exe= cution arrives at the subprocess, a child execution is created. The child executi= on can then later create @@ -1282,14 +1296,14 @@ within the subprocess. In that case, the parent execution is taken= for further continuation of the process. - = + For example, in the following diagram, the "Third task" will only be reached after both the "First task" and the= "Second task" are completed. Completing one of the tasks in the sub-process, wil= l not trigger the continuation of the sub-process, since one execution is still acti= ve within the sub-process. - = + Sub-processes can have multiple start events. In that case, multip= le parallel paths will exist within the sub-process. The rules for sub-process compl= etion are unchanged: @@ -1297,58 +1311,58 @@ ended. - = + Nested sub-processes are also possible. This way, the process can = be divided into several levels of detail. There is no limitation on the levels of nesting. - = + Implementation note: According to the BPMN 2 specification, an act= ivity without ougoing sequence - flow implicitly ends the current execution. However currently, it = is necessary for a correct functioning to = + flow implicitly ends the current execution. However currently, it = is necessary for a correct functioning to specifically use an end event within the sub-process to end a cert= ain path. This will be enhanced in the future to be specification-compliant. - = +
- = +
- = + Timer start event - = + A timer start event is used to indicate that a process should be s= tarted when a given time condition is met. This could be a specific point in time (eg.= October 10th, 2010 at - 5am), but also and more typically a recurring time (eg. every Frid= ay at midnight). = - = - = + 5am), but also and more typically a recurring time (eg. every Frid= ay at midnight). + + A timer start event is visualized as a circle with the clock icon = inside. - = + Using a Timer Start event is done by adding a timerEventDefinition element below the startEvent element: <startEvent name=3D"Every Monday morning" id=3D"myStart&= quot;> <timerEventDefinition/> -</startEvent> = +</startEvent> Following time definitions are possible: timeDate: specifies a fixed= date when a process instance must be created. The default format of the date specification = is - "dd/MM/yyyy hh:mm:ss". This can engine-wide be chang= ed by setting the = + "dd/MM/yyyy hh:mm:ss". This can engine-wide be chang= ed by setting the jbpm.duedatetime.format pro= perty in the configuration. <startEvent id=3D"myStartEvent" > <timerEventDefinition> <timeDate>10/10/2099 00:00:00</timeDa= te> </timerEventDefinition> -</startEvent> = +</startEvent> Note that using a fixed duedate makes the process only useable= for a single time. After the process instance is created, the timer start event w= ill never fire again. @@ -1358,17 +1372,17 @@ process instance will be created. Two types are possible = - Duration expression: = + Duration expression: -quantity [business] {second | seconds | minute | minutes | = - hour | hours | day | days | week | = - weeks | month | months | year | years} = +quantity [business] {second | seconds | minute | minutes | + hour | hours | day | days | week | + weeks | month | months | year | years} - This is completely similar to a timer duration definition= in JPDL. Note that the = + This is completely similar to a timer duration definition= in JPDL. Note that the BPMN2 start timer event also understands "business t= ime". This allows for example to define a "business day" a= s an interval from 9am to 5pm. This way, the time from 5pm to 9am will not b= e taken in account when - the time on which the event will fire is calculated. = + the time on which the event will fire is calculated. Please refer to the JPDL userguide for more details on ho= w this business calendar can be customized. The following example shows a timer start event that will= start a new process instance every five hours. @@ -1377,44 +1391,44 @@ <timerEventDefinition> <timeCycle>5 hours</timeCycle> </timerEventDefinition> -</startEvent> = +</startEvent> Cron expression: - altough duration expressions cover already a great deal of= recurring time definitions, = - sometimes they are not easy to use. = + altough duration expressions cover already a great deal of= recurring time definitions, + sometimes they are not easy to use. When for example a process instance should be started ever= y Friday night 23pm, cron expressions allow a more natural way of defining such= repeating occurrences. The following example shows a timer start event that will = start a new process - instance every Friday at 23pm. = + instance every Friday at 23pm. <startEvent id=3D"myStartEvent" > <timerEventDefinition> <timeCycle>0 0 23 ? * FRI</timeCycle&= gt; </timerEventDefinition> -</startEvent> = +</startEvent> - = + The timer start event implementation in jBPM also has following fe= atures: Process definitions that have a timer start event, can be star= ted as if it also - were a none start event. This means that calling for example = + were a none start event. This means that calling for example executionService.startProcessInstanceByKey(key) just works. The timer start event is internally implemented as a scheduled= job. This means that a job executor has to = be configured for the timer start event to work. The advantage of this implement= ation is that the - timer start event firing is transactional (eg. if a service ta= sks right after the = + timer start event firing is transactional (eg. if a service ta= sks right after the timer start event fails, the transaction will be rolled back a= nd the timer start event will be retried later) and able to cope with a server crash (i= e. the when the server comes back up, the timer start event will be picked up by the = job executor just as if @@ -1422,31 +1436,31 @@ When a new version of a process definition with a timer start = event is deployed, the - old timer start event job is removed from the system. This mea= ns that = + old timer start event job is removed from the system. This mea= ns that only the latest version of the process= definition will be used to create a new process instances. - = + - = +
- = +
- = + Intermediate events - = + An intermediate event is used to model something that happens duri= ng a process (ie. after the process has started and before it is ended). Intermediate even= ts are visualized as a circle with a double border, with an icon indicating the event t= ype within the circle. - = + There are several intermediate event types, such as a timer event,= signal event, escalation event, etc. Intermediate events can be either throwing or catching: - Throwing: when an execution= arrives in the event, it = + Throwing: when an execution= arrives in the event, it immediately fires a certain trigger (a signal, an error, etc.)= . Throwing events can be graphically recognized by the icon that is filled in with b= lack. @@ -1457,19 +1471,19 @@ - = +
- = +
- = + Intermediate catch event: Timer - = + An intermediate timer event is used to represent a delay in the process. Straightfoward use cases are for example polling o= f data, executing heavy logic only at night when nobody is working, etc. - = + Note that an intermediate timer only can be used as a catch event = (throwing a timer event makes no sense). The following diagram shows how the intermediate = timer event is visualized. @@ -1480,26 +1494,26 @@ <timerEventDefinition> <timeCycle>1 hour</timeCycle> </timerEventDefinition> -</intermediateCatchEvent> = +</intermediateCatchEvent> There are two ways to specify the delay, using either a timeCycle or a timeDate. In the example above, a timeCycle is use= d. - = + Following delay definitions are possible (similar to those for a T= imer Start Event). timeDate: specifies a fixed= date when the timer will fire and the process continues. The default format of the date= specification is - "dd/MM/yyyy hh:mm:ss". This can engine-wide be chang= ed by setting the = + "dd/MM/yyyy hh:mm:ss". This can engine-wide be chang= ed by setting the jbpm.duedatetime.format pro= perty in the configuration. <intermediateCatchEvent id=3D"myTimer" > <timerEventDefinition> <timeDate>10/10/2099 00:00:00</timeDa= te> </timerEventDefinition> -</intermediateCatchEvent> = +</intermediateCatchEvent> @@ -1507,13 +1521,13 @@ time when the execution enters the timer event. Two types are = possible = - Duration expression: = + Duration expression: -quantity [business] {second | seconds | minute | minutes | = - hour | hours | day | days | week | = - weeks | month | months | year | years} = +quantity [business] {second | seconds | minute | minutes | + hour | hours | day | days | week | + weeks | month | months | year | years} - This is completely similar to a timer duration definition= in JPDL. Note that the = + This is completely similar to a timer duration definition= in JPDL. Note that the BPMN2 intermediate timer event also understands "bus= iness time". This allows for example to define a "business day" a= s an interval from 9am to 5pm. Timers that are started at 4pm with a duratio= n of 2 hours, will fire @@ -1524,74 +1538,74 @@ <timerEventDefinition> <timeCycle>5 hours</timeCycle> </timerEventDefinition> -</intermediateCatchEvent> = +</intermediateCatchEvent> - Cron expression: altough= duration expressions cover - already a great deal of delay definitions, sometimes they a= re not easy to use. When - for example the process should be delayed until Friday nigh= t 23pm such that the - processes can be executed in the weekend, duration expressi= ons are hard to use - (you need something like "#{calculated_value} seconds&= quot;, where you need - to calculate the value first). - - - = Cron expressions - allow to define delays in a way many people know (since cron= expressions - are used to define scheduled task on Unix machines). Note th= at a cron expression - typically is used to define repetion. In this context howeve= r, the = - first point in time where the cron e= xpression is satisfied - is used to set the due date of the timer event (so no repeti= tion). The following example - shows how an intermediate timer event can be specified to co= ntinue the process - the next friday night at 23pm. - + Cron expression: alto= ugh duration expressions cover + already a great deal of delay definitions, sometimes the= y are not easy to use. When + for example the process should be delayed until Friday n= ight 23pm such that the + processes can be executed in the weekend, duration expre= ssions are hard to use + (you need something like "#{calculated_value} secon= ds", where you need + to calculate the value first). + + + Cron expressions + allow to define delays in a way many people know (since c= ron expressions + are used to define scheduled task on Unix machines). Note= that a cron expression + typically is used to define repetion. In this context how= ever, the + first point in time where the cro= n expression is satisfied + is used to set the due date of the timer event (so no rep= etition). The following example + shows how an intermediate timer event can be specified to= continue the process + the next friday night at 23pm. + <intermediateCatchEvent id=3D"intermediateTimer" > <timerEventDefinition> <timeCycle>0 0 23 ? * FRI</timeCycle&= gt; </timerEventDefinition> -</intermediateCatchEvent> = - - +</intermediateCatchEvent> + + - = +
- = +
- = - = - = + + +
- = + Complete example (including console task forms) - = + Prerequisites: to run the example= , we assume that a working - jBPM console has been installed on your JBoss server. If not, please= run the 'demo.setup.jboss' = + jBPM console has been installed on your JBoss server. If not, please= run the 'demo.setup.jboss' install script first. - = + The business process we're implementing looks as follows: - You might recognize this example, since we=E2=80=99ve also implemented = it in - JPDL as an example in our distribution. - - - The business process is simple: an employee can start a new process and - make a request for a certain amount of vacation days. After the request - task has been completed, the manager will find a verification task in - its tasklist. The Manager can now decide to accept or reject this - request. Depending on the outcome (that=E2=80=99s the little rhombus on= the - outgoing sequence flow - it means there is a conditional expression on = the sequence flow), - a rejection message is send or the process ends. Do note that in fact w= e've used a shortcut - here: instead of putting expressions on the outgoing sequence flow of t= he 'verify request' - task, we've could have used an exclusive gateway after the user task to= control the flow - through the process. Also note that since we haven't implemented swimla= nes yet (probably - the next release), it's difficult to actually see who does what in the = business process. - = - = + You might recognize this example, since we=E2=80=99ve also imp= lemented it in + JPDL as an example in our distribution. + + + The business process is simple: an employee can start a new pr= ocess and + make a request for a certain amount of vacation days. After th= e request + task has been completed, the manager will find a verification = task in + its tasklist. The Manager can now decide to accept or reject t= his + request. Depending on the outcome (that=E2=80=99s the little r= hombus on the + outgoing sequence flow - it means there is a conditional expre= ssion on the sequence flow), + a rejection message is send or the process ends. Do note that = in fact we've used a shortcut + here: instead of putting expressions on the outgoing sequence = flow of the 'verify request' + task, we've could have used an exclusive gateway after the use= r task to control the flow + through the process. Also note that since we haven't implement= ed swimlanes yet (probably + the next release), it's difficult to actually see who does wha= t in the business process. + + The XML version of this process looks as follows: @@ -1657,18 +1671,18 @@ targetRef=3D"theEnd" /> = <endEvent id=3D"theEnd" name=3D"End" /> -</process> = +</process> - Note: this example is already ins= talled when you've = + Note: this example is already ins= talled when you've used the demo setup. Also note that we're using a Script Task here, = to quickly write something as output instead of sending a real message (the diagram i= s showing a Service Task). Also note that we've taken some shortcuts here regarding task= assignment (will be fixed in the next release). - = + The constructs used in this implementation are all covered in the pr= evious section. - Also note that we're using the taskform func= tionality = + Also note that we're using the taskform func= tionality here, which is a custom jBPM extension for the rendering element of a User task. @@ -1683,7 +1697,7 @@ <jbpm:form>org/jbpm/examples/bpmn/usertask/taskform/verify_reque= st.ftl</jbpm:form> </rendering> </userTask> - = + The mechanism regarding task forms for BPMN 2.0 is complete equivale= nt to that of JPDL. The form itself is a Freemarke= r template file that needs to be incorporated in the deployment. For example, the 'v= erify_request.ftl' form @@ -1693,30 +1707,30 @@ <body> = <form action=3D"${form.action}" method=3D"POST"= enctype=3D"multipart/form-data"> - = + <h3>Your employee, ${employee_name} would like to go on vacation</h3> Number of days: ${number_of_days}<br/> - = + <hr> - = + In case you reject, please provide a reason:<br/> <input type=3D"textarea" name= =3D"reason"/><br/> - = + <input type=3D"submit" name=3D&= quot;verificationResult" value=3D"OK"> <input type=3D"submit" name=3D"verificationResult&= quot; value=3D"Not OK"> - = + </form> </body> -</html> = +</html> - Note that process variables can be = + Note that process variables can be accessed using the ${my_process_variable} construct. Also= note that named - input controls (eg. input field, submit button) can be used to = - define new process variables. = + input controls (eg. input field, submit button) can be used to + define new process variables. For example, the text input of the following field will be stored as= the process variable 'reason' -<input type=3D"textarea" name=3D"reason"/> = +<input type=3D"textarea" name=3D"reason"/> Note that there are two submit buttons (which makes sense if you loo= k at the 'OK' and 'Not OK' sequence flows going out the 'request vacation' task. By pressing on= e of these buttons, the @@ -1728,10 +1742,10 @@ <conditionExpression xsi:type=3D"tFormalExpression"> ${verificationResult =3D=3D 'OK'} </conditionExpression> -</sequenceFlow> = +</sequenceFlow> - = + The process can now be deployed. You can use the ant deploy task for= this (see examples), or you can point your jBPM configuration to the database of the cons= ole. To deploy @@ -1741,38 +1755,38 @@ deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/= taskform/vacationrequest.bpmn.xml"); deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/= taskform/request_vacation.ftl"); deployment.addResourceFromClasspath("org/jbpm/examples/bpmn/usertask/= taskform/verify_request.ftl"); -deployment.deploy(); = +deployment.deploy(); - You can now embed (or run on a standalone server) this business proc= ess, by using the = - familiar jBPM API operations. For example, process instances can now= be started using the = + You can now embed (or run on a standalone server) this business proc= ess, by using the + familiar jBPM API operations. For example, process instances can now= be started using the key (ie. the process id for BPMN 2.0): -ProcessInstance pi =3D executionService.startProcessInstanceByKey("va= cationRequestProcess"); = +ProcessInstance pi =3D executionService.startProcessInstanceByKey("va= cationRequestProcess"); Or tasks list can be retrieved: -Task requestTasktask =3D taskService.createTaskQuery().candidate("pet= er").uniqueResult(); = +Task requestTasktask =3D taskService.createTaskQuery().candidate("pet= er").uniqueResult(); - = + When deploying to the jBPM console database, you should see our new = business process popping up. - = + After you start a new process, a new task should be available in the= employee's tasklist. When clicking on 'view', the task form will be displayed, requesting= to fill in some variables for further use in the process. - = + After task completion, the manager will find a new verification task= in his task list. He can now accept or reject the vacation request, based on the input= of the employee. - = + Since the database schema remains unchanged when we added BPMN 2.0 on= top of the jBPM PVM, all existing reports can be applied to our new BPMN 2.0 processes. - = +
- = +
Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/depl= oyment/Bpmn2DeploymentTest.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/deployment= /Bpmn2DeploymentTest.java 2010-10-16 13:44:02 UTC (rev 6764) +++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/deployment= /Bpmn2DeploymentTest.java 2010-10-17 14:44:27 UTC (rev 6765) @@ -35,8 +35,8 @@ * @author Joram Barrez */ public class Bpmn2DeploymentTest extends JbpmTestCase { - = - private static final String TEST_PROCESS_ONLY_ID =3D = + + private static final String TEST_PROCESS_ONLY_ID =3D "" + " " + " " + @@ -44,8 +44,8 @@ " " + " " + ""; - = - private static final String TEST_PROCESS_ONLY_NAME =3D = + + private static final String TEST_PROCESS_ONLY_NAME =3D "" + " " + " " + @@ -53,8 +53,8 @@ " " + " " + ""; - = - private static final String TEST_PROCESS_ID_AND_NAME =3D = + + private static final String TEST_PROCESS_ID_AND_NAME =3D "" + " " + " " + @@ -62,84 +62,88 @@ " " + " " + ""; - = + public void testDeployProcessWithOnlyName() { try { deployBpmn2XmlString(TEST_PROCESS_ONLY_NAME); fail(); } catch (JbpmException e) { // Exception is to be expected + String newLine =3D System.getProperty("line.separator"); + assertEquals(newLine + " error: attribute definitions =3D query.list(); assertEquals(1, definitions.size()); - = + deployBpmn2XmlString(TEST_PROCESS_ONLY_ID); query.orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION); definitions =3D query.list(); - = + assertEquals(2, definitions.size()); assertEquals(1, definitions.get(0).getVersion()); assertEquals(2, definitions.get(1).getVersion()); - = + // Check if the key is replaced with the name (query should give same = result) List definitionsByName =3D repositoryService.create= ProcessDefinitionQuery() .processDefinitio= nName("myProcess").list(); CollectionAssertions.assertContainsSameElements(definitions, definitio= nsByName); } - = + public void testRedeployProcessWithIdAndName() { deployBpmn2XmlString(TEST_PROCESS_ID_AND_NAME); - = - ProcessDefinitionQuery query =3D repositoryService.createProcessDefini= tionQuery().processDefinitionName("myProcess"); + + ProcessDefinitionQuery query =3D repositoryService.createProcessDefini= tionQuery() + .processDefinitionName= ("myFirstProcess"); List definitions =3D query.list(); assertEquals(1, definitions.size()); - = + deployBpmn2XmlString(TEST_PROCESS_ID_AND_NAME); query.orderAsc(ProcessDefinitionQuery.PROPERTY_VERSION); definitions =3D query.list(); - = + assertEquals(2, definitions.size()); assertEquals(1, definitions.get(0).getVersion()); assertEquals(2, definitions.get(1).getVersion()); - = + // Check if the key is replaced with the name (query should give same = result) List definitionsByKey =3D repositoryService.createP= rocessDefinitionQuery() - .processDefinitio= nKey("myFirstProcess").list(); + .processDefinitio= nKey("myProcess").list(); CollectionAssertions.assertContainsSameElements(definitions, definitio= nsByKey); } - = + } Modified: jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/star= tevent/TimerStartEventTest.java =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent= /TimerStartEventTest.java 2010-10-16 13:44:02 UTC (rev 6764) +++ jbpm4/trunk/modules/test-db/src/test/java/org/jbpm/bpmn/test/startevent= /TimerStartEventTest.java 2010-10-17 14:44:27 UTC (rev 6765) @@ -123,7 +123,7 @@ = private static final String TIMER_START_TIMECYCLE_CRON_EXPR =3D "= " + - " " + + " " + " " + " " + " 0 0 22 * * ?" + // every day at 22:00 --===============2819330918473443660==--