一种全新的工作流引擎,通过状态机实现 (This is a full new workflow engine,it is business object-oriented. i trying modify the apache commons SCXML to suppot this.)
本工作流引擎采用了状态机的思想,使用W3C 的SCXML 标准,在Apache Commons SCXML基础上做的更改。 This worfklow engine adopt the idea of state machine. we use W3C's SCXML standard and modify the Apache Commons SCXML
<userTask id="judge" name="JudgeTask" assiginee="" candidateGroups="Judger" instancesExpr="judgeCount">
<form name="" src="">
<param name="taskName" expr="taskNameValue" type="input"></param>
<param name="taskDescription" expr="taskDescriptionValue" type="input"></param>
</form>
</userTask>
<ServiceTask>
</ServiceTask>
<subStateMachine src="subStateMachineProcessDefinePath" instances="numberOfSubStateMachine">
<param name="" value=""></param>
<param name="" value=""></param>
</subStateMachine>
自定义的支持8种 状态机之间通信的消息模式(Custom 8 message mode to support communication between multi-state-machine )
<send event="eventName" type="scxml" messageMode="TO_PARENT" targetName="StateMachineName" targetState="currentStateOfTargetStateMachine"></send>
the messageMode include {BROADCAST, TO_OFFSPRING,TO_CHILD,TO_SIBLING,TO_ANCESTOR,MULTICAST,TO_PARENT,UNICAST;}
IdentityService.createUserQuery().userName("").userEmail("").singleResult();
//more
RuntimeService.createProcessInstanceQuery().processId("").singleResult();
RuntimeService.createProcessInstanceQuery().getAllProcessInstance();
//more
支持用户任务,和群组任务,支持签收功能(support single user and group task query and sign in function)
TaskService.createUserTaskQuery("").taskName("").taskId("").taskFinish("").taskAssignee("").taskProcessId("");
TaskService.createGroupTaskQuery("").taskName("").taskId("").taskCandidateGroup("");
//more
支持动态表单和外接表单(Support dynamic form and external form)
FormService.createFormQuery().formId();
//more
filename: crowdsourcingTest.xml
, you can find a crowdsourcing application here :!()[https://github.com/ThinerZQ/CrowdSourcing/tree/problem]
<?xml version="1.0"?>
<scxml xmlns="http://www.w3.org/2005/07/scxml"
version="1.0"
datamodel="jexl"
initial="init"
name="crowdsourcing">
<!-- some property needed -->
<datamodel>
<data id="deployee" expr=""></data>
<data id="taskName" expr=""></data>
<data id="taskDescription" expr=""></data>
<data id="dueDate"></data>
<data id="judgeCount" expr=""></data>
<data id="decomposeCount" expr=""></data>
<data id="decomposeVoteCount" expr=""></data>
<data id="solveCount" expr=""></data>
<data id="solveVoteCount" expr=""></data>
<data id="steps" expr="0"></data>
</datamodel>
<!-- the properties of current Object to be initialized-->
<state id="init">
<onentry>
<log label="init" expr="'init state entry ,begin to initialization'"/>
<script>
taskName=crowdSourcingTask.getTaskName();
taskDescription=crowdSourcingTask.getTaskDescription();
judgeCount = crowdSourcingTask.getTaskJudgeCount();
decomposeCount= crowdSourcingTask.getTaskDecomposeCount();
decomposeVoteCount= crowdSourcingTask.getTaskDecomposeVoteCount();
solveCount= crowdSourcingTask.getTaskSolveCount();
solveVoteCount= crowdSourcingTask.getTaskSolveVoteCount();
</script>
<log label="init" expr="'initialization complete'"></log>
</onentry>
<transition target="judging">
<log label="init" expr="'init state transition to judging'"/>
</transition>
<onexit>
<log label="init" expr="'init state exit'"/>
</onexit>
</state>
<!-- JudgeState, To determine whether the current task is a simple task-->
<state id="judging">
<datamodel>
<data id="complexCount" expr="0"></data>
<data id="simpleCount" expr="0"></data>
</datamodel>
<onentry>
<log label="judging" expr="'entry judging state'"/>
<userTask id="judge" name="JudgeTask" candidateGroups="Judger" instancesExpr="judgeCount">
<form src="form/judge.jsp">
</form>
</userTask>
</onentry>
<onexit>
<log label="judging" expr="'exit judging state'"/>
</onexit>
<transition event="judgeComplete">
<if cond="_event.data.simple eq 0">
<assign location="simpleCount" expr="simpleCount + 1"></assign>
<log label="judging" expr="' simple'"/>
<elseif cond="_event.data.simple eq 1"/>
<assign location="complexCount" expr="complexCount + 1"></assign>
<log label="judging" expr="' complex'"/>
<else/>
<log label="judging" expr="_event.data.simple"/>
</if>
<if cond="simpleCount + complexCount eq judgeCount">
<send event="judgeCompleted"></send>
<log label="judging" expr="'send event judgeCompleted'"/>
</if>
<log label="judging" expr="'judge state inner transition'"/>
</transition>
<transition event="judgeCompleted" cond="simpleCount gt complexCount" target="solving">
<log label="judging" expr="'judge state transition to solving'"/>
</transition>
<transition event="judgeCompleted" cond="simpleCount lt complexCount" target="decomposing">
<log label="judging" expr="'judge state transition to decomposing'"/>
</transition>
</state>
<!-- decomposing state : if current task is complex task ,it will enter this state and ,it will be decomposed by some Decomposer -->
<state id="decomposing">
<datamodel>
<data id="counted" expr="0"></data>
<data id="step" expr="0"></data>
</datamodel>
<onentry>
<log label="decomposing" expr="'entry decomposing state'"/>
<userTask id="decompose" name="DecomposeTask" candidateGroups="Decomposer"
instancesExpr="decomposeCount">
<form src="form/decompose.jsp">
</form>
</userTask>
</onentry>
<transition event="decomposeComplete">
<assign location="counted" expr="counted + 1"></assign>
<!-- 写入数据库: 谁分解成了什么 -->
<log label="decomposing" expr="' inner transition ,decomposeComplete'"/>
</transition>
<transition cond="counted eq decomposeCount" target="decomposeVoting">
<log label="decomposing" expr="' transition from decompose to decomposeVoting '"/>
</transition>
<onexit>
<log label="decomposing" expr="'exit decomposing state'"/>
</onexit>
</state>
<!-- DecomposeVoting state , when several decomposer have voted, current task will be voted for best decomposition strategy -->
<state id="decomposeVoting">
<datamodel>
<data id="counted" expr="0"></data>
</datamodel>
<onentry>
<userTask id="decompose" name="DecomposeVoteTask" candidateGroups="DecomposeVoter"
instancesExpr="decomposeVoteCount">
<form src="form/decomposeVote.jsp">
</form>
</userTask>
<log label="decomposeVoting" expr="'entry decomposeVoting state'"/>
</onentry>
<transition event="decomposeVoteComplete">
<assign location="counted" expr="counted + 1"></assign>
<log label="decomposeVoting" expr="' inner transition ,decomposeVoteComplete'"/>
</transition>
<transition event="startSubMachine" cond="counted eq decomposeVoteCount" target="waitResulting">
<!-- start substaemachine, you can set up crowdSourcingTaskArrayList object in runtime -->
<foreach array="crowdSourcingTaskArrayList" item="tempCrowdSourcingTask">
<subStateMachine src="crowdsourcingTest.xml" instances="1">
<param name="crowdSourcingTask" expr="tempCrowdSourcingTask"></param>
</subStateMachine>
<assign location="steps" expr="steps + 1"></assign>
<log label="decomposeVoting" expr="'startSubMachine '"/>
</foreach>
<log label="decomposeVoting" expr="'transition from decompose to decomposeVoting '"/>
</transition>
</state>
<!-- wait children's event come -->
<state id="waitResulting">
<datamodel>
<data id="count" expr="0"></data>
</datamodel>
<onentry>
<log label="waitResulting" expr="'entry waitResulting state '"/>
</onentry>
<!-- receive event from child -->
<transition event="to_waitResult">
<assign location="count" expr="count + 1"></assign>
<log label="waitResulting" expr="' inner transition ,subStateMachine_to_end'"/>
</transition>
<transition cond="count eq steps" target="merging">
<log label="waitResulting" expr="' transition from waitResulting to merging '"/>
</transition>
</state>
<!-- assign merging task -->
<state id="merging">
<datamodel>
<data id="count" expr="0"></data>
</datamodel>
<onentry>
<log label="merging" expr="'entry merging state '"/>
<!-- Merge algorithm here called -->
<script>
result = crowdSourcingTask.merge();
</script>
</onentry>
<transition cond="result" target="end">
<!-- send event to parent state machine -->
<send event="to_waitResult" type="scxml" messageMode="TO_PARENT"></send>
<log label="merging" expr="'transition from merging state to end '"/>
</transition>
</state>
<!-- Solving state -->
<state id="solving">
<datamodel>
<data id="counted" expr="0"></data>
</datamodel>
<onentry>
<log label="solving" expr="'entry solving state '"/>
<userTask id="solve" name="SolveTask" candidateGroups="Solver"
instancesExpr="solveCount">
<form src="form/solve.jsp">
</form>
</userTask>
</onentry>
<transition event="solveComplete">
<assign location="counted" expr="counted + 1"></assign>
<log label="solving" expr="'solveComplete ,inner transition '"/>
</transition>
<transition cond="counted eq solveCount" target="solveVoting">
<log label="solving" expr="' transition from solving to solveVoting'"/>
</transition>
</state>
<!-- SolveVoting state -->
<state id="solveVoting">
<datamodel>
<data id="counted" expr="0"></data>
</datamodel>
<onentry>
<log label="solveVoting" expr="' entry solveVoting state '"/>
<userTask id="solveVoting" name="SolveVoteTask" candidateGroups="SolveVoter"
instancesExpr="solveVoteCount">
<form src="form/solveVote.jsp">
</form>
</userTask>
</onentry>
<transition event="solveVoteComplete">
<assign location="counted" expr="counted + 1"></assign>
<log label="solveVoting" expr="'solveVoteComplete ,inner transition '"/>
</transition>
<transition cond="counted eq solveVoteCount" target="end">
<!-- send evetn to parent state machine -->
<send event="to_waitResult" type="scxml" messageMode="TO_PARENT"></send>
<log label="solveVoting" expr="'transition from solveVoting to end '"/>
</transition>
</state>
<!-- end state -->
<final id="end">
<onentry>
<log label="end" expr="' crowdsourcingTask end '"/>
</onentry>
</final>
</scxml>