5 PLATFORM SPECIFIC IMPLEMENTATION
5.3 Content via RM
5.5.1 Process Runtime Environment: The Web Process Engine
The process runtime environment, or Web process engine, is a part the generic runtime en- vironment presented in 5.1.2. The runtime environment contains a list of available process activities and further holds a reference to the currently active process activity, if any. Within the method handleRequest of the main controller depicted in Figure 75 the control
flow is delegated to the Web process engine if either a new process should be started, or the next step of the currently active process should be executed. For more details about the integration of processes in the runtime environment see 5.1.2.
The process runtime environment is represented by the collection of process activities of a Web application. In Figure 84 the implementation classes for the execution of a process activity are outlined. The name of the process class representing a process is comprised as an attribute of the corresponding process activity. This reference is needed in the runtime environment to identify the invocation of a process. A process activity comprises a list of activity nodes and set of activity edges. Activity nodes can hold a token which is either a control token, indicating that a flow of control is currently at a specific node, or an object token which indicates that an object flow is at a specific node. Activity edges represent the possible flow of tokens from one activity node to another. Multiple tokens may be present at different activity nodes at a specific point in time. The method acceptsToken of an activ-
ity node or an activity edge is used to query if a specific token would currently be accepted which then could be received by the method receiveToken. An activity has an input pa-
rameter node and optionally an output parameter node which serve to hold input and output object tokens.
Model Driven Software Engineering for Web Applications
ActivityNode
-name : St ring
+accept sToken( t : Token ) : boolean +get Cont extObject() : Object +get Cont rolToken() : Cont rolToken +get Nam e() : St ring
+get ObjectToken() : Object Token +get Token() : Token
+get ViewName() : String +hasToken() : boolean +init() +isWaitingForInput() : boolean +next() : boolean +processInput () +receiveToken( t : Token ) +removeToken() ProcessActivity -contextObject : Object -entr yNode : St ring -exit Node : String -f inished : boolean -input Par am eter : Object -name : St ring -processClass : Str ing -viewName : St ring +get Cont extObject() : Object +get ViewName() : St ring +init( inputParamet er : Object ) +isFinished() : boolean +next ()
ActivityEdge
-guard : Object = null
+accept sToken( t : Token ) : boolean +receiveToken( t : Token ) ActivityParameterNode ObjectToken -object : Object +getObject() : Object ControlToken ObjectNode ControlNode Action ControlFlow ObjectFlow Token * +outputParameterNode 0..1 0..1 +inputParameterNode 1 +source 1 +outgoing * +target 1 +incoming * * {ordered}
Figure 84. Runtime process activity
In Figure 85 the different kind of control nodes supported by the process engine are de- picted. The implementation of these nodes corresponds to the UML specification as de- fined in [OMG05a]. In comparison to Figure 48, decision and merge nodes are imple- mented by a common class DecisionMergeNode, and fork and join nodes by a common
class ForkJoinNode, because most modeling tools do not clearly differentiate the corre-
sponding node types. Figure 86 comprises the different kind of object nodes of a process activity supported here which are also compliant with the UML specification, cf. 4.5.2. Pins represent input and output of actions and activity parameter nodes the input and out- put of process activities, respectively. A central buffer node is used for intermediate buffer- ing of object tokens while a datastore node represents a permanent (i.e. during the execu- tion of the activity) buffer.
DecisionMergeNode
ActivityFinalNode FlowFinalNode
ForkJoinNode
ControlNode
FinalNode
Figure 85. Runtime control nodes
ActivityParameterNode DataStoreNode CentralBufferNode ObjectNode OutputPin InputPin Pin
Figure 86. Runtime object nodes
The different kinds of actions supported here are depicted in Figure 87. Input and output pins are associated to actions. An action starts its execution when tokens are available at all input pins. If optionally a control flow is entering the action an additional control token is required. After completion of an action the result data is available at the output pins, and an additional control token is available at the corresponding outgoing control flow, if a control flow is leaving from the action. The call operation action executes fully automatically by invoking a method on the target object. The call behavior action is used to compose proc- ess activities and controls the execution of a subordinated process activity (other kinds of subordinated behavior are not supported, hence the difference to Figure 47). Finally, a user action represents an interaction with the user. When it is ready to be executed, i.e. all re- quired input and control tokens are available, then it indicates that it is waiting for input. The corresponding user interaction object for the input is returned by calling the method
Model Driven Software Engineering for Web Applications UserAction -processClass : String CallOperationAction -m et hodName : String ProcessActivity CallBehaviorAction OutputPin InputPin Action * {ordered} +input * {ordered} +output 1 +target 1
Figure 87. Runtime actions
Before starting the execution of a process activity it has to be initialized by calling the method init. This results in initializing all activity nodes and placing an object token in the
input parameter node as illustrated by the following simplified Java code lines:
public void init( Object inputParameter ) {
// initialize all activity nodes
for( ActivityNode n : activityNodes ) n.init(); // place new object token in input parameter node
inputParameterNode.receiveToken( new ObjectToken( inputParameter ) ); this.inputParameter = inputParameter;
finished = false; }
The complete execution of a process activity comprises the handling of user interactions. Thus, when a process activity contains at least one user interaction then it cannot be exe- cuted completely in one step. This is the case if a process activity contains at least one user action either directly, or indirectly by containing a call behavior action that calls another process activity that contains a user interaction. The method next of a process activity is
called from the runtime environment to execute the process activity until the next user in- teraction is encountered or the process activity has finished its execution, see 5.1.2. More- over, either the next user interaction object to be presented to the user is saved in the at- tribute contextObj, or the output parameter object if the activity has finished with a return
value. The following code lines give an outline to the implementation of the method next:
public void next() {
// process input requested after last method call for( ActivityNode n : activityNodes )
{ if( n.isWaitingForInput() ) { n.processInput(); break; } }
// token passing loop while( true )
{
boolean progress = false;
for( ActivityNode n : activityNodes ) {
progress |= n.next();
// return in case of waiting for user input if( n.isWaitingForInput() ) { contextObject = n.getContextObject(); viewName = n.getViewName(); return; }
// finish activity and return in case that the output parameter node has an object token else if( n == outputParameterNode && n.hasToken() )
{
finished = true;
contextObject = outputParameterNode.getObjectToken().getObject(); viewName = exitNode;
}
// finish activity and return in case of reached activity final node else if( n instanceof ActivityFinalNode && n.hasToken() ) { finished = true; contextObject = inputParameter; viewName = entryNode; return; } }
Model Driven Software Engineering for Web Applications
// throw an exception if no progress has been made if( !progress ) throw new ProcessActivityStallException(); }
}
First the method processInput of the first activity node that was waiting for input in the last
step is called to process the user input that is now available in the user interaction object. Then all activity nodes are notified to execute its behavior by calling the method next. If a
node then indicates that is waiting for input the method returns with the user interaction object returned by this node. If a token arrives either at an activity output parameter node or at an activity final node the execution of the process activity terminates and the method returns. After a full loop over all activity nodes a progress must have been made. Then the loop is repeated. Each activity node therefore has to indicate on returning from the method
next if it made a progress. If no progress has been made an exception is thrown to indicate
that the progress of the process activity has stalled.
A detailed example for the execution of processes in the runtime environment is given in 6.2.3.
5.5.2 Example
As already stated and in contrast to the content and presentation concerns of a Web appli- cation, the process model is not transformed to code in a specific programming language but to configuration data of the runtime environment. As explained in 5.1.3 this configura- tion data has the form of XML bean nodes which represent the objects of the process run- time environment and their properties as depicted in Figure 84 to Figure 87. On instantia- tion of these configuration beans the runtime environment gets initialized with the avail- able process activities which correspond to the process model. The following example shows an excerpt from the serialized XML bean definition document process-conf.xml for
the process activity and the input activity parameter node of the process RemoveProject
depicted in Figure 57. <bean class="uwe.runtime.process.ProcessActivity" id="ProcessActivity_DANUBIA_Process_RemoveProject_RemoveProject"> <property name="name"><value>RemoveProject</value></property> <property name="processClass"> <value>DANUBIA_Process_RemoveProject</value> </property> <property name="entryNode"> <value>DANUBIA_Navigation_ProjectManager</value> 199
</property>
<property name="activityNodes"> <list>
<ref bean="ActivityParameterNode _DANUBIA_Process _RemoveProject_RemoveProject_ProjectManager"></ref> … </list> </property> <property name="activityEdges"> <list> … </list> </property> <property name="inputParameterNode"> <ref bean="ActivityParameterNode_DANUBIA_Process _RemoveProject_RemoveProject_ProjectManager"></ref> </property> </bean>
<bean class="uwe.runtime.process.ActivityParameterNode" id="ActivityParameterNode_DANUBIA _Process _RemoveProject_RemoveProject_ProjectManager"> <property name="name"><value>ProjectManager</value></property> <property name="activity"> <ref bean="ProcessActivity_DANUBIA_Navigation_RemoveProject_RemoveProject"></ref> </property> <property name="incoming"><list></list></property> <property name="outgoing"><list>…</list></property> </bean> … 5.5.3 Transformation Process2Conf
The transformation Process2Conf depicted in Figure 88 maps the process model to con-
figuration data for the process runtime environment. Therefore the transformation rules defined in 5.1.3.2 are reused. For each class of the process runtime environment depicted in Figure 84 to Figure 87 a transformation rule which specializes the rule NamedEle- ment2Conf defined in 5.1.3.2 is responsible for mapping the corresponding model elements
from the process model to a bean node in the XML configuration model. Two basic rules for mapping process activities and activity nodes are outlined in the following. The later is an abstract rule that is specialized by sub rules. The rule inheritance hierarchy corresponds to the class inheritance hierarchy of the classes for the process runtime environment de- picted in Figure 84 to Figure 87. Finally, the resulting XML model is serialized to the