<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Recent changes to workflow</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>Recent changes to workflow</description><atom:link href="https://sourceforge.net/p/lightj/wiki/workflow/feed" rel="self"/><language>en</language><lastBuildDate>Thu, 26 Jan 2012 09:35:11 -0000</lastBuildDate><atom:link href="https://sourceforge.net/p/lightj/wiki/workflow/feed" rel="self" type="application/rss+xml"/><item><title>WikiPage workflow modified by Bin Yu</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>&lt;pre&gt;--- v7 
+++ v8 
@@ -32,5 +32,5 @@
 * FlowEvent enum defines flowevent generated by the framework at runtime
 * FlowEventListener interface to handle flow event
 
-###Learn More###
+###To Learn More###
 For more details, check out LightJ source code package org.lightj.session.*, examples in lightj-examples.zip at download section
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Bin Yu</dc:creator><pubDate>Thu, 26 Jan 2012 09:35:11 -0000</pubDate><guid>https://sourceforge.net2cf7ec00c3bed0ef2166c85109c70e5247ec670f</guid></item><item><title>WikiPage workflow modified by Bin Yu</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>&lt;pre&gt;--- v6 
+++ v7 
@@ -31,3 +31,6 @@
 * FlowStepProperty annotation for step properties eg. weight
 * FlowEvent enum defines flowevent generated by the framework at runtime
 * FlowEventListener interface to handle flow event
+
+###Learn More###
+For more details, check out LightJ source code package org.lightj.session.*, examples in lightj-examples.zip at download section
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Bin Yu</dc:creator><pubDate>Thu, 26 Jan 2012 09:34:58 -0000</pubDate><guid>https://sourceforge.net8bb21f90126a6fe6d40be72847cf0d6e453dfecf</guid></item><item><title>WikiPage workflow modified by Bin Yu</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>&lt;pre&gt;--- v5 
+++ v6 
@@ -31,202 +31,3 @@
 * FlowStepProperty annotation for step properties eg. weight
 * FlowEvent enum defines flowevent generated by the framework at runtime
 * FlowEventListener interface to handle flow event
-
-###Usage example###
-
-&lt;b&gt;Create a flow and define its steps and properties&lt;/b&gt;
-&lt;pre&gt;
-&lt;code&gt;
-@FlowDefinition(typeId=22, desc="hello world", group="TEST")
-@FlowProperties(clusterSafe=true,crashSafe=true)
-public class HelloWorldFlow extends FlowSession&lt;HelloWorldFlowContext&gt; {
-	
-	public static enum steps {
-		@FlowStepProperties(stepWeight=0)
-		start,
-		@FlowStepProperties(stepWeight=1)
-		syncTaskStep,
-		@FlowStepProperties(stepWeight=2)
-		asyncTaskStep,
-		@FlowStepProperties(stepWeight=2)
-		splitStep,
-		@FlowStepProperties(stepWeight=3)
-		forLoopStep,
-		@FlowStepProperties(stepWeight=3)
-		whileLoopStep,
-		@FlowStepProperties(stepWeight=3)
-		sessionJoinStep,
-		@FlowStepProperties(stepWeight=5)
-		scheduledStep,
-		@FlowStepProperties(stepWeight=0)
-		stop,
-		error,
-	}
-
-	private IFlowStep asyncTaskStep;
-	private IFlowStep splitStep;
-	private IFlowStep forLoopStep;
-	private IFlowStep whileLoopStep;
-
-	@Override
-	protected Enum getFirstStepEnum() {
-		return steps.start;
-	}
-
-	/** shared error handler */
-	private StepErrorHandler errorHandler = new MappedErrorHandler(new StepTransition(steps.error));
-	
-	/**
-	 * start step, synchronous
-	 * demonstrate how to execute a synchronous step
-	 * @return
-	 */
-	public IFlowStep start() {
-		StepExecution execution = new SimpleStepExecution(new StepTransition(getParentId()&gt;0 ? steps.stop : steps.syncTaskStep));
-
-		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
-	}
-	
-	/**
-	 * step to execute a task by task runner
-	 * demonstrate how to execute a runtask asynchronous step
-	 * @return
-	 */
-	public IFlowStep asyncTaskStep() 
-	{
-		return asyncTaskStep;
-	}
-
-&lt;/code&gt;
-&lt;/pre&gt;
-&lt;pre&gt;
-&lt;b&gt;Create a flow context to keep data&lt;/b&gt;
-&lt;code&gt;
-public class HelloWorldFlowContext extends FlowContext {
-
-	static final String META_COUNT	=	"META_COUNT";
-	static final String META_SPLIT_COUNT	=	"META_SPLIT_COUNT";
-	static final String META_FORLOOP_COUNT	=	"META_FORLOOP_COUNT";
-	static final String META_WHILELOOP_COUNT	=	"META_WHILELOOP_COUNT";
-	
-	public void setScheduledRunCount(int count) {
-		setIntParam(META_COUNT, count);
-	}
-	public int getScheduledRunCount() {
-		return getIntParam(META_COUNT, 0);
-	}
-&lt;/code&gt;
-&lt;/pre&gt;
-&lt;pre&gt;
-&lt;b&gt;Create one step in the flow by a step factory and build-in Split enclosure&lt;/b&gt;
-&lt;code&gt;
-public class HelloWorldFlowStepsImpl {
-	
-	private static StepErrorHandler&lt;HelloWorldFlowContext&gt; errorHandler = new MappedErrorHandler&lt;HelloWorldFlowContext&gt;(new StepTransition(steps.error));
-
-	public static IFlowStep buildSplitStep() {
-		IFlowStep step = null;
-		Collection&lt;StepExecution&gt; executions = new ArrayList&lt;StepExecution&gt;();
-		for (int i = 0; i &lt; 3; i++) {
-			StepExecution&lt;HelloWorldFlowContext&gt; execution = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(StepTransition.NOOP) {
-				public StepTransition execute() throws FlowExecutionException {
-					int cnt = sessionContext.getSplitCount();
-					sessionContext.setSplitCount(++cnt);
-					System.out.println("in split step: " + cnt);
-					return super.execute();
-				}
-			};
-			executions.add(execution);
-		}
-		
-		StepExecution&lt;HelloWorldFlowContext&gt; mergeCheck = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(
-				StepTransition.runToStep(steps.forLoopStep)) {
-			public StepTransition execute() throws FlowExecutionException {
-				System.out.println("in split step merge: " + sessionContext.getSplitCount());
-				return super.execute();
-			}
-		};
-		
-		step = new SplitEnclosure()
-				.foreachSplit(SplitOption.MaxProgress, executions, errorHandler, 2)
-				.merge(MergeOption.SynchronizeOnExecution, mergeCheck)
-				.getFlowStep();
-		return step;
-	}
-
-&lt;/code&gt;
-&lt;/pre&gt;
-&lt;pre&gt;
-&lt;b&gt;Wire everything together by spring bean&lt;/b&gt;
-&lt;code&gt;
-&lt;beans xmlns="http://www.springframework.org/schema/beans"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
-	xmlns:context="http://www.springframework.org/schema/context"
-	xmlns:util="http://www.springframework.org/schema/util"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
-		http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd 
-		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd 
-		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
-
-	&lt;bean id="flowFactory" class="org.lightj.session.FlowSessionFactory" factory-method="getInstance" /&gt;
-	
-	&lt;bean id="simpleLocatable" class="org.lightj.dal.SimpleLocatable" scope="prototype" /&gt;
-	
-	&lt;bean id="asyncTaskStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildAsyncTaskStep" /&gt;
-	
-	&lt;bean id="splitStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildSplitStep" /&gt;
-
-	&lt;bean id="forLoopStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildForLoopStep" /&gt;
-	
-	&lt;bean id="whileLoopStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildWhileLoopStep" /&gt;
-	
-
-	&lt;bean id="helloWorldFlow" factory-bean="flowFactory" factory-method="createSession"&gt;
-		&lt;constructor-arg index="0" type="java.lang.Class" value="org.lightj.example.session.HelloWorldFlow"&gt;&lt;/constructor-arg&gt;
-		&lt;constructor-arg index="1" type="org.lightj.dal.Locatable" ref="simpleLocatable"/&gt;
-		&lt;constructor-arg index="2" type="org.lightj.dal.Locatable" ref="simpleLocatable"/&gt;
-		&lt;property name="asyncTaskStep" ref="asyncTaskStep"/&gt;
-		&lt;property name="splitStep" ref="splitStep" /&gt;
-		&lt;property name="forLoopStep" ref="forLoopStep" /&gt;
-		&lt;property name="whileLoopStep" ref="whileLoopStep" /&gt;
-	&lt;/bean&gt;
-	
-&lt;/beans&gt;
-
-&lt;/code&gt;
-&lt;/pre&gt;
-&lt;pre&gt;
-&lt;b&gt;Initialize and run it&lt;/b&gt;
-&lt;code&gt;
-
-	@Override
-	protected BaseModule[] getDependentModules() {
-		String ctxPath = "config/org/lightj/session/context-flow.xml";
-		String taskCtxPath = "config/org/lightj/task/context-task.xml";
-		return new BaseModule[] {
-				new TaskModule().setSpringContext(taskCtxPath).getModule(),
-				new FlowModule().setDb(SampleDatabaseEnum.QRTZ)
-								.enableCluster()
-								.setSpringContext(ctxPath)
-								.getModule(),
-		};
-	}
-
-	public void testHelloWorldWithDI() throws Exception {
-		ApplicationContext ctx = SpringContextUtil.loadContext("helloworld", "config/org/lightj/session/context-helloworld-flow.xml");
-		HelloWorldFlow session = (HelloWorldFlow) ctx.getBean("helloWorldFlow");
-		
-		// use DI to set step impl
-		FlowSessionFactory.getInstance().save(session);
-		session.addEventListener(new HelloWorldFlowEventListener(lock, cond));
-		session.runFlow();
-		ConcurrentUtil.wait(lock, cond);
-		Assert.assertEquals(3, session.getSessionContext().getScheduledRunCount());
-		Assert.assertEquals(3, session.getSessionContext().getSplitCount());
-		Assert.assertEquals(2, session.getSessionContext().getForLoopCount());
-		Assert.assertEquals(2, session.getSessionContext().getWhileLoopCount());
-	}
-
-&lt;/code&gt;
-
-&lt;/pre&gt;
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Bin Yu</dc:creator><pubDate>Thu, 26 Jan 2012 09:31:26 -0000</pubDate><guid>https://sourceforge.net140a169d8731492e4f83e19a4d34faf343d0b6cc</guid></item><item><title>WikiPage workflow modified by Bin Yu</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>&lt;pre&gt;--- v4 
+++ v5 
@@ -35,200 +35,198 @@
 ###Usage example###
 
 &lt;b&gt;Create a flow and define its steps and properties&lt;/b&gt;
-&lt;code&gt;
-
+&lt;pre&gt;
+&lt;code&gt;
 @FlowDefinition(typeId=22, desc="hello world", group="TEST")
 @FlowProperties(clusterSafe=true,crashSafe=true)
 public class HelloWorldFlow extends FlowSession&lt;HelloWorldFlowContext&gt; {
 	
 	public static enum steps {
 		@FlowStepProperties(stepWeight=0)
 		start,
 		@FlowStepProperties(stepWeight=1)
 		syncTaskStep,
 		@FlowStepProperties(stepWeight=2)
 		asyncTaskStep,
 		@FlowStepProperties(stepWeight=2)
 		splitStep,
 		@FlowStepProperties(stepWeight=3)
 		forLoopStep,
 		@FlowStepProperties(stepWeight=3)
 		whileLoopStep,
 		@FlowStepProperties(stepWeight=3)
 		sessionJoinStep,
 		@FlowStepProperties(stepWeight=5)
 		scheduledStep,
 		@FlowStepProperties(stepWeight=0)
 		stop,
 		error,
 	}
 
 	private IFlowStep asyncTaskStep;
 	private IFlowStep splitStep;
 	private IFlowStep forLoopStep;
 	private IFlowStep whileLoopStep;
 
 	@Override
 	protected Enum getFirstStepEnum() {
 		return steps.start;
 	}
 
 	/** shared error handler */
 	private StepErrorHandler errorHandler = new MappedErrorHandler(new StepTransition(steps.error));
 	
 	/**
 	 * start step, synchronous
 	 * demonstrate how to execute a synchronous step
 	 * @return
 	 */
 	public IFlowStep start() {
 		StepExecution execution = new SimpleStepExecution(new StepTransition(getParentId()&gt;0 ? steps.stop : steps.syncTaskStep));
 
 		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
 	}
 	
 	/**
 	 * step to execute a task by task runner
 	 * demonstrate how to execute a runtask asynchronous step
 	 * @return
 	 */
 	public IFlowStep asyncTaskStep() 
 	{
 		return asyncTaskStep;
 	}
 
 &lt;/code&gt;
-&lt;pre&gt;
-
-&lt;/pre&gt;
+&lt;/pre&gt;
+&lt;pre&gt;
 &lt;b&gt;Create a flow context to keep data&lt;/b&gt;
 &lt;code&gt;
 public class HelloWorldFlowContext extends FlowContext {
 
 	static final String META_COUNT	=	"META_COUNT";
 	static final String META_SPLIT_COUNT	=	"META_SPLIT_COUNT";
 	static final String META_FORLOOP_COUNT	=	"META_FORLOOP_COUNT";
 	static final String META_WHILELOOP_COUNT	=	"META_WHILELOOP_COUNT";
 	
 	public void setScheduledRunCount(int count) {
 		setIntParam(META_COUNT, count);
 	}
 	public int getScheduledRunCount() {
 		return getIntParam(META_COUNT, 0);
 	}
 &lt;/code&gt;
-&lt;pre&gt;
-
-&lt;/pre&gt;
+&lt;/pre&gt;
+&lt;pre&gt;
 &lt;b&gt;Create one step in the flow by a step factory and build-in Split enclosure&lt;/b&gt;
 &lt;code&gt;
 public class HelloWorldFlowStepsImpl {
 	
 	private static StepErrorHandler&lt;HelloWorldFlowContext&gt; errorHandler = new MappedErrorHandler&lt;HelloWorldFlowContext&gt;(new StepTransition(steps.error));
 
 	public static IFlowStep buildSplitStep() {
 		IFlowStep step = null;
 		Collection&lt;StepExecution&gt; executions = new ArrayList&lt;StepExecution&gt;();
 		for (int i = 0; i &lt; 3; i++) {
 			StepExecution&lt;HelloWorldFlowContext&gt; execution = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(StepTransition.NOOP) {
 				public StepTransition execute() throws FlowExecutionException {
 					int cnt = sessionContext.getSplitCount();
 					sessionContext.setSplitCount(++cnt);
 					System.out.println("in split step: " + cnt);
 					return super.execute();
 				}
 			};
 			executions.add(execution);
 		}
 		
 		StepExecution&lt;HelloWorldFlowContext&gt; mergeCheck = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(
 				StepTransition.runToStep(steps.forLoopStep)) {
 			public StepTransition execute() throws FlowExecutionException {
 				System.out.println("in split step merge: " + sessionContext.getSplitCount());
 				return super.execute();
 			}
 		};
 		
 		step = new SplitEnclosure()
 				.foreachSplit(SplitOption.MaxProgress, executions, errorHandler, 2)
 				.merge(MergeOption.SynchronizeOnExecution, mergeCheck)
 				.getFlowStep();
 		return step;
 	}
 
 &lt;/code&gt;
-&lt;pre&gt;
-
-&lt;/pre&gt;
+&lt;/pre&gt;
+&lt;pre&gt;
 &lt;b&gt;Wire everything together by spring bean&lt;/b&gt;
 &lt;code&gt;
 &lt;beans xmlns="http://www.springframework.org/schema/beans"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
 	xmlns:context="http://www.springframework.org/schema/context"
 	xmlns:util="http://www.springframework.org/schema/util"
 	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 		http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd 
 		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd 
 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
 
 	&lt;bean id="flowFactory" class="org.lightj.session.FlowSessionFactory" factory-method="getInstance" /&gt;
 	
 	&lt;bean id="simpleLocatable" class="org.lightj.dal.SimpleLocatable" scope="prototype" /&gt;
 	
 	&lt;bean id="asyncTaskStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildAsyncTaskStep" /&gt;
 	
 	&lt;bean id="splitStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildSplitStep" /&gt;
 
 	&lt;bean id="forLoopStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildForLoopStep" /&gt;
 	
 	&lt;bean id="whileLoopStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildWhileLoopStep" /&gt;
 	
 
 	&lt;bean id="helloWorldFlow" factory-bean="flowFactory" factory-method="createSession"&gt;
 		&lt;constructor-arg index="0" type="java.lang.Class" value="org.lightj.example.session.HelloWorldFlow"&gt;&lt;/constructor-arg&gt;
 		&lt;constructor-arg index="1" type="org.lightj.dal.Locatable" ref="simpleLocatable"/&gt;
 		&lt;constructor-arg index="2" type="org.lightj.dal.Locatable" ref="simpleLocatable"/&gt;
 		&lt;property name="asyncTaskStep" ref="asyncTaskStep"/&gt;
 		&lt;property name="splitStep" ref="splitStep" /&gt;
 		&lt;property name="forLoopStep" ref="forLoopStep" /&gt;
 		&lt;property name="whileLoopStep" ref="whileLoopStep" /&gt;
 	&lt;/bean&gt;
 	
 &lt;/beans&gt;
 
 &lt;/code&gt;
-&lt;pre&gt;
-
-&lt;/pre&gt;
+&lt;/pre&gt;
+&lt;pre&gt;
 &lt;b&gt;Initialize and run it&lt;/b&gt;
 &lt;code&gt;
 
 	@Override
 	protected BaseModule[] getDependentModules() {
 		String ctxPath = "config/org/lightj/session/context-flow.xml";
 		String taskCtxPath = "config/org/lightj/task/context-task.xml";
 		return new BaseModule[] {
 				new TaskModule().setSpringContext(taskCtxPath).getModule(),
 				new FlowModule().setDb(SampleDatabaseEnum.QRTZ)
 								.enableCluster()
 								.setSpringContext(ctxPath)
 								.getModule(),
 		};
 	}
 
 	public void testHelloWorldWithDI() throws Exception {
 		ApplicationContext ctx = SpringContextUtil.loadContext("helloworld", "config/org/lightj/session/context-helloworld-flow.xml");
 		HelloWorldFlow session = (HelloWorldFlow) ctx.getBean("helloWorldFlow");
 		
 		// use DI to set step impl
 		FlowSessionFactory.getInstance().save(session);
 		session.addEventListener(new HelloWorldFlowEventListener(lock, cond));
 		session.runFlow();
 		ConcurrentUtil.wait(lock, cond);
 		Assert.assertEquals(3, session.getSessionContext().getScheduledRunCount());
 		Assert.assertEquals(3, session.getSessionContext().getSplitCount());
 		Assert.assertEquals(2, session.getSessionContext().getForLoopCount());
 		Assert.assertEquals(2, session.getSessionContext().getWhileLoopCount());
 	}
 
 &lt;/code&gt;
+
+&lt;/pre&gt;
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Bin Yu</dc:creator><pubDate>Tue, 02 Aug 2011 06:37:16 -0000</pubDate><guid>https://sourceforge.net46d689653e11ae91bdbfee4ea84aefb25e6f92b7</guid></item><item><title>WikiPage workflow modified by Bin Yu</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>&lt;pre&gt;--- v3 
+++ v4 
@@ -98,102 +98,108 @@
 	}
 
 &lt;/code&gt;
-
+&lt;pre&gt;
+
+&lt;/pre&gt;
 &lt;b&gt;Create a flow context to keep data&lt;/b&gt;
 &lt;code&gt;
 public class HelloWorldFlowContext extends FlowContext {
 
 	static final String META_COUNT	=	"META_COUNT";
 	static final String META_SPLIT_COUNT	=	"META_SPLIT_COUNT";
 	static final String META_FORLOOP_COUNT	=	"META_FORLOOP_COUNT";
 	static final String META_WHILELOOP_COUNT	=	"META_WHILELOOP_COUNT";
 	
 	public void setScheduledRunCount(int count) {
 		setIntParam(META_COUNT, count);
 	}
 	public int getScheduledRunCount() {
 		return getIntParam(META_COUNT, 0);
 	}
 &lt;/code&gt;
-
+&lt;pre&gt;
+
+&lt;/pre&gt;
 &lt;b&gt;Create one step in the flow by a step factory and build-in Split enclosure&lt;/b&gt;
 &lt;code&gt;
 public class HelloWorldFlowStepsImpl {
 	
 	private static StepErrorHandler&lt;HelloWorldFlowContext&gt; errorHandler = new MappedErrorHandler&lt;HelloWorldFlowContext&gt;(new StepTransition(steps.error));
 
 	public static IFlowStep buildSplitStep() {
 		IFlowStep step = null;
 		Collection&lt;StepExecution&gt; executions = new ArrayList&lt;StepExecution&gt;();
 		for (int i = 0; i &lt; 3; i++) {
 			StepExecution&lt;HelloWorldFlowContext&gt; execution = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(StepTransition.NOOP) {
 				public StepTransition execute() throws FlowExecutionException {
 					int cnt = sessionContext.getSplitCount();
 					sessionContext.setSplitCount(++cnt);
 					System.out.println("in split step: " + cnt);
 					return super.execute();
 				}
 			};
 			executions.add(execution);
 		}
 		
 		StepExecution&lt;HelloWorldFlowContext&gt; mergeCheck = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(
 				StepTransition.runToStep(steps.forLoopStep)) {
 			public StepTransition execute() throws FlowExecutionException {
 				System.out.println("in split step merge: " + sessionContext.getSplitCount());
 				return super.execute();
 			}
 		};
 		
 		step = new SplitEnclosure()
 				.foreachSplit(SplitOption.MaxProgress, executions, errorHandler, 2)
 				.merge(MergeOption.SynchronizeOnExecution, mergeCheck)
 				.getFlowStep();
 		return step;
 	}
 
 &lt;/code&gt;
-
-
+&lt;pre&gt;
+
+&lt;/pre&gt;
 &lt;b&gt;Wire everything together by spring bean&lt;/b&gt;
 &lt;code&gt;
 &lt;beans xmlns="http://www.springframework.org/schema/beans"
 	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
 	xmlns:context="http://www.springframework.org/schema/context"
 	xmlns:util="http://www.springframework.org/schema/util"
 	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
 		http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd 
 		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd 
 		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
 
 	&lt;bean id="flowFactory" class="org.lightj.session.FlowSessionFactory" factory-method="getInstance" /&gt;
 	
 	&lt;bean id="simpleLocatable" class="org.lightj.dal.SimpleLocatable" scope="prototype" /&gt;
 	
 	&lt;bean id="asyncTaskStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildAsyncTaskStep" /&gt;
 	
 	&lt;bean id="splitStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildSplitStep" /&gt;
 
 	&lt;bean id="forLoopStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildForLoopStep" /&gt;
 	
 	&lt;bean id="whileLoopStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildWhileLoopStep" /&gt;
 	
 
 	&lt;bean id="helloWorldFlow" factory-bean="flowFactory" factory-method="createSession"&gt;
 		&lt;constructor-arg index="0" type="java.lang.Class" value="org.lightj.example.session.HelloWorldFlow"&gt;&lt;/constructor-arg&gt;
 		&lt;constructor-arg index="1" type="org.lightj.dal.Locatable" ref="simpleLocatable"/&gt;
 		&lt;constructor-arg index="2" type="org.lightj.dal.Locatable" ref="simpleLocatable"/&gt;
 		&lt;property name="asyncTaskStep" ref="asyncTaskStep"/&gt;
 		&lt;property name="splitStep" ref="splitStep" /&gt;
 		&lt;property name="forLoopStep" ref="forLoopStep" /&gt;
 		&lt;property name="whileLoopStep" ref="whileLoopStep" /&gt;
 	&lt;/bean&gt;
 	
 &lt;/beans&gt;
 
 &lt;/code&gt;
-
-
+&lt;pre&gt;
+
+&lt;/pre&gt;
 &lt;b&gt;Initialize and run it&lt;/b&gt;
 &lt;code&gt;
 
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Bin Yu</dc:creator><pubDate>Tue, 02 Aug 2011 06:30:05 -0000</pubDate><guid>https://sourceforge.netc2d7100342d662a93bac65cbe4be955cb8c4a0f8</guid></item><item><title>WikiPage workflow modified by Bin Yu</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>&lt;pre&gt;--- v2 
+++ v3 
@@ -32,351 +32,197 @@
 * FlowEvent enum defines flowevent generated by the framework at runtime
 * FlowEventListener interface to handle flow event
 
-###Sample session source code###
-
-&lt;code&gt;
-package org.lightj.example.session;
-
-import java.io.InvalidObjectException;
-
-import org.lightj.dal.DataAccessException;
-import org.lightj.dal.SimpleLocatable;
-import org.lightj.schedule.ISchedule;
-import org.lightj.schedule.ScheduleException;
-import org.lightj.schedule.SchedulerFactory;
-import org.lightj.session.FlowDefinition;
-import org.lightj.session.FlowExecutionException;
-import org.lightj.session.FlowInitializationException;
-import org.lightj.session.FlowProperties;
-import org.lightj.session.FlowResult;
-import org.lightj.session.FlowSession;
-import org.lightj.session.FlowSessionFactory;
-import org.lightj.session.FlowState;
-import org.lightj.session.FlowStepProperties;
-import org.lightj.session.step.AsyncTaskStepExecution;
-import org.lightj.session.step.IFlowStep;
-import org.lightj.session.step.MappedCallbackHandler;
-import org.lightj.session.step.MappedErrorHandler;
-import org.lightj.session.step.ScheduledStepBuilder;
-import org.lightj.session.step.SimpleStepExecution;
-import org.lightj.session.step.StepBuilder;
-import org.lightj.session.step.StepErrorHandler;
-import org.lightj.session.step.StepExecution;
-import org.lightj.session.step.StepTransition;
-import org.lightj.task.ITaskRunnerKeys;
-import org.lightj.task.Task;
-import org.lightj.task.TaskResult;
-import org.lightj.task.session.FlowJoinTask;
-import org.lightj.task.session.FlowJoinTaskResult;
-import org.lightj.task.session.FlowTaskResult;
-
-
+###Usage example###
+
+&lt;b&gt;Create a flow and define its steps and properties&lt;/b&gt;
+&lt;code&gt;
+
 @FlowDefinition(typeId=22, desc="hello world", group="TEST")
 @FlowProperties(clusterSafe=true,crashSafe=true)
-@SuppressWarnings("unchecked")
 public class HelloWorldFlow extends FlowSession&lt;HelloWorldFlowContext&gt; {
 	
 	public static enum steps {
 		@FlowStepProperties(stepWeight=0)
 		start,
 		@FlowStepProperties(stepWeight=1)
 		syncTaskStep,
 		@FlowStepProperties(stepWeight=2)
 		asyncTaskStep,
 		@FlowStepProperties(stepWeight=2)
 		splitStep,
 		@FlowStepProperties(stepWeight=3)
 		forLoopStep,
 		@FlowStepProperties(stepWeight=3)
 		whileLoopStep,
 		@FlowStepProperties(stepWeight=3)
 		sessionJoinStep,
 		@FlowStepProperties(stepWeight=5)
 		scheduledStep,
 		@FlowStepProperties(stepWeight=0)
 		stop,
 		error,
 	}
 
-	/**
-	 * demonstrate how to do DI for individual step, see {@link HelloWorldFlowStepsImpl}
-	 */
 	private IFlowStep asyncTaskStep;
 	private IFlowStep splitStep;
 	private IFlowStep forLoopStep;
 	private IFlowStep whileLoopStep;
 
-	public IFlowStep getAsyncTaskStep() {
-		return asyncTaskStep;
-	}
-
-	public void setAsyncTaskStep(IFlowStep asyncTaskStep) {
-		this.asyncTaskStep = asyncTaskStep;
-	}
-
-	public IFlowStep getSplitStep() {
-		return splitStep;
-	}
-
-	public void setSplitStep(IFlowStep slipStep) {
-		this.splitStep = slipStep;
-	}
-
-	public IFlowStep getForLoopStep() {
-		return forLoopStep;
-	}
-
-	public void setForLoopStep(IFlowStep forLoopStep) {
-		this.forLoopStep = forLoopStep;
-	}
-
-	public IFlowStep getWhileLoopStep() {
-		return whileLoopStep;
-	}
-
-	public void setWhileLoopStep(IFlowStep whileLoopStep) {
-		this.whileLoopStep = whileLoopStep;
-	}
-
-	public HelloWorldFlow() {
-		super();
-	}
-
 	@Override
 	protected Enum getFirstStepEnum() {
 		return steps.start;
 	}
 
 	/** shared error handler */
 	private StepErrorHandler errorHandler = new MappedErrorHandler(new StepTransition(steps.error));
 	
 	/**
 	 * start step, synchronous
 	 * demonstrate how to execute a synchronous step
 	 * @return
 	 */
 	public IFlowStep start() {
 		StepExecution execution = new SimpleStepExecution(new StepTransition(getParentId()&gt;0 ? steps.stop : steps.syncTaskStep));
 
 		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
 	}
 	
 	/**
-	 * synchronous execution
-	 * @return
-	 */
-	public IFlowStep syncTaskStep() {
-		StepExecution execution = new SimpleStepExecution(StepTransition.NOOP) {
-
-			public StepTransition execute() throws FlowExecutionException {
-				// do something here
-				return new StepTransition(steps.asyncTaskStep);
-			}
-
-		};
-
-		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
-	}
-	
-	/**
 	 * step to execute a task by task runner
 	 * demonstrate how to execute a runtask asynchronous step
 	 * @return
 	 */
 	public IFlowStep asyncTaskStep() 
 	{
 		return asyncTaskStep;
 	}
-	
-	/**
-	 * step to execute a few task in parallel, and merge
-	 * @return
-	 */
-	public IFlowStep splitStep() {
-		return splitStep;
-	}
-	
-	/**
-	 * step to execute a task in for loop
-	 * @return
-	 */
-	public IFlowStep forLoopStep() {
-		return forLoopStep;
-	}
-	
-	/**
-	 * step to execute a task in while loop
-	 * @return
-	 */
-	public IFlowStep whileLoopStep() {
-		return whileLoopStep;
-	}
-	
-	/**
-	 * step to launch child session(s) and join on return
-	 * demonstrate how to execute a session join asynchronous task
-	 * @return
-	 */
-	public IFlowStep sessionJoinStep() throws Exception {
-		// build execution
-		StepExecution execution = new JoinStepExecution();
-
-		// callback handler
-		JoinStepCallbackHandler resultHandler = new JoinStepCallbackHandler(
-				StepTransition.runToStep(steps.scheduledStep.name()));
-		
-		// build the step
-		return new StepBuilder().execute(execution, errorHandler).onCallback(resultHandler, errorHandler).getFlowStep();
-	}
-	
-	/**
-	 * a schedule step to repeatly execute something on a customized schedule
-	 * demonstrate how to execute a loop/scheduled task for looping 3 times 
-	 * @return
-	 */
-	public IFlowStep scheduledStep() throws Exception {
-
-		try {
-			final String scheduleName = "Dummy flow session " + this.getKeyOfTarget();
-			ISchedule schedule = SchedulerFactory.getInstance(SchedulerFactory.SCHEDULER_TRANSIENT).createSchedule(scheduleName);
-			schedule.executeRecur(
-					null, 
-					ISchedule.NO_END_DATE, 
-					5, 
-					10
-			);
-			StepExecution execution = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(StepTransition.NOOP) {
-					
-						public StepTransition execute() throws FlowExecutionException {
-							int cnt = sessionContext.getScheduledRunCount();
-							cnt++;
-							sessionContext.setScheduledRunCount(cnt);
-							return (cnt &gt;= 3) ? new StepTransition(steps.stop.name()) : StepTransition.NOOP;
-						}
-						
+
+&lt;/code&gt;
+
+&lt;b&gt;Create a flow context to keep data&lt;/b&gt;
+&lt;code&gt;
+public class HelloWorldFlowContext extends FlowContext {
+
+	static final String META_COUNT	=	"META_COUNT";
+	static final String META_SPLIT_COUNT	=	"META_SPLIT_COUNT";
+	static final String META_FORLOOP_COUNT	=	"META_FORLOOP_COUNT";
+	static final String META_WHILELOOP_COUNT	=	"META_WHILELOOP_COUNT";
+	
+	public void setScheduledRunCount(int count) {
+		setIntParam(META_COUNT, count);
+	}
+	public int getScheduledRunCount() {
+		return getIntParam(META_COUNT, 0);
+	}
+&lt;/code&gt;
+
+&lt;b&gt;Create one step in the flow by a step factory and build-in Split enclosure&lt;/b&gt;
+&lt;code&gt;
+public class HelloWorldFlowStepsImpl {
+	
+	private static StepErrorHandler&lt;HelloWorldFlowContext&gt; errorHandler = new MappedErrorHandler&lt;HelloWorldFlowContext&gt;(new StepTransition(steps.error));
+
+	public static IFlowStep buildSplitStep() {
+		IFlowStep step = null;
+		Collection&lt;StepExecution&gt; executions = new ArrayList&lt;StepExecution&gt;();
+		for (int i = 0; i &lt; 3; i++) {
+			StepExecution&lt;HelloWorldFlowContext&gt; execution = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(StepTransition.NOOP) {
+				public StepTransition execute() throws FlowExecutionException {
+					int cnt = sessionContext.getSplitCount();
+					sessionContext.setSplitCount(++cnt);
+					System.out.println("in split step: " + cnt);
+					return super.execute();
+				}
 			};
-			return new ScheduledStepBuilder()
-						.execute(execution, errorHandler)
-						.schedule(new StepTransition(steps.stop.name()),	schedule)
-						.getFlowStep();
-		} 
-		catch (ScheduleException e) {
-			throw new FlowExecutionException(e);
-		}
-		
-	}
-	
-	/**
-	 * erorr complete step
-	 * @return
-	 */
-	public IFlowStep error() {
-		StepExecution execution = new SimpleStepExecution(
-				new StepTransition().inState(FlowState.Completed).withResult(FlowResult.Failed));
-
-		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
-	}
-	
-	/**
-	 * normal complete step
-	 * @return
-	 */
-	public IFlowStep stop() {
-		StepExecution execution = new SimpleStepExecution(
-				new StepTransition().inState(FlowState.Completed).withResult(FlowResult.Success));
-
-		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
-	}
-	
-	/**
-	 * run a join child session step
-	 * @author biyu
-	 *
-	 */
-	class JoinStepExecution extends AsyncTaskStepExecution&lt;HelloWorldFlowContext&gt; {
-
-		public JoinStepExecution() {
-			super(null, ITaskRunnerKeys.SessionTaskRunner);
-		}
-		
-		private Task buildTask() {
-			FlowJoinTask joinTask = new FlowJoinTask();
-			boolean allSaved = false;
-			try {
-				for (int i = 0; i &lt; 2; i++) {
-					FlowSession child = FlowSessionFactory.getInstance().createChildSession(
-							HelloWorldFlow.class, 
-							new SimpleLocatable(),
-							HelloWorldFlow.this);
-					FlowSessionFactory.getInstance().save(child);
-					joinTask.addSessions(child);
-				}
-				allSaved = true;
-			} catch (FlowInitializationException e) {
-				throw new FlowExecutionException(e);
-			} catch (DataAccessException e) {
-				throw new FlowExecutionException(e);
-			} catch (InvalidObjectException e) {
-				throw new FlowExecutionException(e);
-			} catch (Throwable t) {
-				throw new RuntimeException(t);
-			} finally {
-				if (!allSaved) {
-					joinTask.cancel("Not all child sessions are saved successfully");
-				}
-			}
-			return joinTask;
-		}
-		
-		@Override
-		public StepTransition execute() throws FlowExecutionException {
-			
-			this.task = buildTask();
-			
-			return super.execute();
-		}
-		
-	}
-
-	/**
-	 * customized callback handler for join step
-	 * demonstrate how to do more business logic in handling task result
-	 * @author biyu
-	 *
-	 */
-	static class JoinStepCallbackHandler extends MappedCallbackHandler {
-		
-		public JoinStepCallbackHandler(StepTransition transition) {
-			super(transition);
-		}
-
-		@Override
-		public StepTransition executeOnResult(TaskResult result) throws FlowExecutionException {
-			StepTransition transition = defResult;
-			if (result instanceof FlowTaskResult) {
-				// individual child session completes
-				transition = new StepTransition().withResult(convertStatus(result)).log(result.getMsg());
-			}
-			return transition;
-		}
-
-		@Override
-		public StepTransition executeOnCompleted(TaskResult result) throws FlowExecutionException {
-			String msg = result.getMsg();
-			StepTransition transition = defResult;
-			if (result instanceof FlowJoinTaskResult) {
-				// all child sessions complete
-				if (result.isSuccess()) { // success
-					transition = new StepTransition(steps.scheduledStep.name()).withResult(FlowResult.Success).log(msg);
-				}
-				else { // cancelled, timeout, or failed
-					transition = new StepTransition(steps.error.name()).withResult(FlowResult.Failed).log(msg);
-				}
-			}
-			return transition;
-		}
-
-	}
-	
-}
+			executions.add(execution);
+		}
+		
+		StepExecution&lt;HelloWorldFlowContext&gt; mergeCheck = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(
+				StepTransition.runToStep(steps.forLoopStep)) {
+			public StepTransition execute() throws FlowExecutionException {
+				System.out.println("in split step merge: " + sessionContext.getSplitCount());
+				return super.execute();
+			}
+		};
+		
+		step = new SplitEnclosure()
+				.foreachSplit(SplitOption.MaxProgress, executions, errorHandler, 2)
+				.merge(MergeOption.SynchronizeOnExecution, mergeCheck)
+				.getFlowStep();
+		return step;
+	}
+
+&lt;/code&gt;
+
+
+&lt;b&gt;Wire everything together by spring bean&lt;/b&gt;
+&lt;code&gt;
+&lt;beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:camel="http://camel.apache.org/schema/spring"
+	xmlns:context="http://www.springframework.org/schema/context"
+	xmlns:util="http://www.springframework.org/schema/util"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+		http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd 
+		http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd 
+		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"&gt;
+
+	&lt;bean id="flowFactory" class="org.lightj.session.FlowSessionFactory" factory-method="getInstance" /&gt;
+	
+	&lt;bean id="simpleLocatable" class="org.lightj.dal.SimpleLocatable" scope="prototype" /&gt;
+	
+	&lt;bean id="asyncTaskStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildAsyncTaskStep" /&gt;
+	
+	&lt;bean id="splitStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildSplitStep" /&gt;
+
+	&lt;bean id="forLoopStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildForLoopStep" /&gt;
+	
+	&lt;bean id="whileLoopStep" class="org.lightj.example.session.HelloWorldFlowStepsImpl" factory-method="buildWhileLoopStep" /&gt;
+	
+
+	&lt;bean id="helloWorldFlow" factory-bean="flowFactory" factory-method="createSession"&gt;
+		&lt;constructor-arg index="0" type="java.lang.Class" value="org.lightj.example.session.HelloWorldFlow"&gt;&lt;/constructor-arg&gt;
+		&lt;constructor-arg index="1" type="org.lightj.dal.Locatable" ref="simpleLocatable"/&gt;
+		&lt;constructor-arg index="2" type="org.lightj.dal.Locatable" ref="simpleLocatable"/&gt;
+		&lt;property name="asyncTaskStep" ref="asyncTaskStep"/&gt;
+		&lt;property name="splitStep" ref="splitStep" /&gt;
+		&lt;property name="forLoopStep" ref="forLoopStep" /&gt;
+		&lt;property name="whileLoopStep" ref="whileLoopStep" /&gt;
+	&lt;/bean&gt;
+	
+&lt;/beans&gt;
+
+&lt;/code&gt;
+
+
+&lt;b&gt;Initialize and run it&lt;/b&gt;
+&lt;code&gt;
+
+	@Override
+	protected BaseModule[] getDependentModules() {
+		String ctxPath = "config/org/lightj/session/context-flow.xml";
+		String taskCtxPath = "config/org/lightj/task/context-task.xml";
+		return new BaseModule[] {
+				new TaskModule().setSpringContext(taskCtxPath).getModule(),
+				new FlowModule().setDb(SampleDatabaseEnum.QRTZ)
+								.enableCluster()
+								.setSpringContext(ctxPath)
+								.getModule(),
+		};
+	}
+
+	public void testHelloWorldWithDI() throws Exception {
+		ApplicationContext ctx = SpringContextUtil.loadContext("helloworld", "config/org/lightj/session/context-helloworld-flow.xml");
+		HelloWorldFlow session = (HelloWorldFlow) ctx.getBean("helloWorldFlow");
+		
+		// use DI to set step impl
+		FlowSessionFactory.getInstance().save(session);
+		session.addEventListener(new HelloWorldFlowEventListener(lock, cond));
+		session.runFlow();
+		ConcurrentUtil.wait(lock, cond);
+		Assert.assertEquals(3, session.getSessionContext().getScheduledRunCount());
+		Assert.assertEquals(3, session.getSessionContext().getSplitCount());
+		Assert.assertEquals(2, session.getSessionContext().getForLoopCount());
+		Assert.assertEquals(2, session.getSessionContext().getWhileLoopCount());
+	}
+
 &lt;/code&gt;
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Bin Yu</dc:creator><pubDate>Tue, 02 Aug 2011 06:26:22 -0000</pubDate><guid>https://sourceforge.net0be7077df35cf884a8b00697391e39d9ffb55ec0</guid></item><item><title>WikiPage workflow modified by Bin Yu</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>&lt;pre&gt;--- v1 
+++ v2 
@@ -1,373 +1,375 @@
-*LightJ embedded workflow engine is a lightweight framework implemented in pure java with no more than 30 core classes, support the following features*
-
+###Features###
+
+LightJ embedded workflow engine is a lightweight framework implemented in pure java with no more than 30 core classes, support the following features
+
 * Persistent or transient state by choice (currently support mysql, oracle, and hsqldb)
 * Persistent or transient execution context by choice
 * Crash recovery
 * Cluster safe (cluster implementation based on shoal/grizzly GMS)
 * Built-in synchronous, asynchronous, split/merge, loop, schedule execution pattern support
 * Built-in error handling, no error will “fall through the crack”
 * Built-in logging and flow event handling
 * Many built-in flow fine tune features by annotations.
 * Nested flows or flow join support
 * Standard flow control interface, start, stop, pause, resume, kill
 * Flow validation at initialization, straightforward initialization and registration
 * Spring compatible, flow can be initialized by spring DI
 * Workflow logic and transition completely built by java, easy to learn, easy to use, easy to support
 * Minimal external dependencies, no complicated XML workflow definition in XML
 
-*Key design*
+###Key design###
 
 * Workflow implementation by extending FlowSession base class
 * FlowDefinition annotation for flow information, and concurrent execution grouping
 * FlowStep enum provide state definition of the flow
 * Each enum value in FlowStep enum maps to a method in flow implementation using the same name, the method is responsible of building the execution logic for the step
 * StepExecution contains execution logic for a flow step, there are 2 main flavors
 * StepTransition is returned by a FlowStepExecution and provide information of state transition.
 * FlowContext contains context information that can be persisted and accessed each step of the way
 * FlowDrive drives the flow from start to end or to as far as it can be run.
 * FlowProperty for flow specific properties eg. cluster, recovery, concurrency etc.
 * FlowStepProperty annotation for step properties eg. weight
 * FlowEvent enum defines flowevent generated by the framework at runtime
 * FlowEventListener interface to handle flow event
 
-*Sample session source code*
-
-{code}
+###Sample session source code###
+
+&lt;code&gt;
 package org.lightj.example.session;
 
 import java.io.InvalidObjectException;
 
 import org.lightj.dal.DataAccessException;
 import org.lightj.dal.SimpleLocatable;
 import org.lightj.schedule.ISchedule;
 import org.lightj.schedule.ScheduleException;
 import org.lightj.schedule.SchedulerFactory;
 import org.lightj.session.FlowDefinition;
 import org.lightj.session.FlowExecutionException;
 import org.lightj.session.FlowInitializationException;
 import org.lightj.session.FlowProperties;
 import org.lightj.session.FlowResult;
 import org.lightj.session.FlowSession;
 import org.lightj.session.FlowSessionFactory;
 import org.lightj.session.FlowState;
 import org.lightj.session.FlowStepProperties;
 import org.lightj.session.step.AsyncTaskStepExecution;
 import org.lightj.session.step.IFlowStep;
 import org.lightj.session.step.MappedCallbackHandler;
 import org.lightj.session.step.MappedErrorHandler;
 import org.lightj.session.step.ScheduledStepBuilder;
 import org.lightj.session.step.SimpleStepExecution;
 import org.lightj.session.step.StepBuilder;
 import org.lightj.session.step.StepErrorHandler;
 import org.lightj.session.step.StepExecution;
 import org.lightj.session.step.StepTransition;
 import org.lightj.task.ITaskRunnerKeys;
 import org.lightj.task.Task;
 import org.lightj.task.TaskResult;
 import org.lightj.task.session.FlowJoinTask;
 import org.lightj.task.session.FlowJoinTaskResult;
 import org.lightj.task.session.FlowTaskResult;
 
 
 @FlowDefinition(typeId=22, desc="hello world", group="TEST")
 @FlowProperties(clusterSafe=true,crashSafe=true)
 @SuppressWarnings("unchecked")
 public class HelloWorldFlow extends FlowSession&lt;HelloWorldFlowContext&gt; {
 	
 	public static enum steps {
 		@FlowStepProperties(stepWeight=0)
 		start,
 		@FlowStepProperties(stepWeight=1)
 		syncTaskStep,
 		@FlowStepProperties(stepWeight=2)
 		asyncTaskStep,
 		@FlowStepProperties(stepWeight=2)
 		splitStep,
 		@FlowStepProperties(stepWeight=3)
 		forLoopStep,
 		@FlowStepProperties(stepWeight=3)
 		whileLoopStep,
 		@FlowStepProperties(stepWeight=3)
 		sessionJoinStep,
 		@FlowStepProperties(stepWeight=5)
 		scheduledStep,
 		@FlowStepProperties(stepWeight=0)
 		stop,
 		error,
 	}
 
 	/**
 	 * demonstrate how to do DI for individual step, see {@link HelloWorldFlowStepsImpl}
 	 */
 	private IFlowStep asyncTaskStep;
 	private IFlowStep splitStep;
 	private IFlowStep forLoopStep;
 	private IFlowStep whileLoopStep;
 
 	public IFlowStep getAsyncTaskStep() {
 		return asyncTaskStep;
 	}
 
 	public void setAsyncTaskStep(IFlowStep asyncTaskStep) {
 		this.asyncTaskStep = asyncTaskStep;
 	}
 
 	public IFlowStep getSplitStep() {
 		return splitStep;
 	}
 
 	public void setSplitStep(IFlowStep slipStep) {
 		this.splitStep = slipStep;
 	}
 
 	public IFlowStep getForLoopStep() {
 		return forLoopStep;
 	}
 
 	public void setForLoopStep(IFlowStep forLoopStep) {
 		this.forLoopStep = forLoopStep;
 	}
 
 	public IFlowStep getWhileLoopStep() {
 		return whileLoopStep;
 	}
 
 	public void setWhileLoopStep(IFlowStep whileLoopStep) {
 		this.whileLoopStep = whileLoopStep;
 	}
 
 	public HelloWorldFlow() {
 		super();
 	}
 
 	@Override
 	protected Enum getFirstStepEnum() {
 		return steps.start;
 	}
 
 	/** shared error handler */
 	private StepErrorHandler errorHandler = new MappedErrorHandler(new StepTransition(steps.error));
 	
 	/**
 	 * start step, synchronous
 	 * demonstrate how to execute a synchronous step
 	 * @return
 	 */
 	public IFlowStep start() {
 		StepExecution execution = new SimpleStepExecution(new StepTransition(getParentId()&gt;0 ? steps.stop : steps.syncTaskStep));
 
 		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
 	}
 	
 	/**
 	 * synchronous execution
 	 * @return
 	 */
 	public IFlowStep syncTaskStep() {
 		StepExecution execution = new SimpleStepExecution(StepTransition.NOOP) {
 
 			public StepTransition execute() throws FlowExecutionException {
 				// do something here
 				return new StepTransition(steps.asyncTaskStep);
 			}
 
 		};
 
 		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
 	}
 	
 	/**
 	 * step to execute a task by task runner
 	 * demonstrate how to execute a runtask asynchronous step
 	 * @return
 	 */
 	public IFlowStep asyncTaskStep() 
 	{
 		return asyncTaskStep;
 	}
 	
 	/**
 	 * step to execute a few task in parallel, and merge
 	 * @return
 	 */
 	public IFlowStep splitStep() {
 		return splitStep;
 	}
 	
 	/**
 	 * step to execute a task in for loop
 	 * @return
 	 */
 	public IFlowStep forLoopStep() {
 		return forLoopStep;
 	}
 	
 	/**
 	 * step to execute a task in while loop
 	 * @return
 	 */
 	public IFlowStep whileLoopStep() {
 		return whileLoopStep;
 	}
 	
 	/**
 	 * step to launch child session(s) and join on return
 	 * demonstrate how to execute a session join asynchronous task
 	 * @return
 	 */
 	public IFlowStep sessionJoinStep() throws Exception {
 		// build execution
 		StepExecution execution = new JoinStepExecution();
 
 		// callback handler
 		JoinStepCallbackHandler resultHandler = new JoinStepCallbackHandler(
 				StepTransition.runToStep(steps.scheduledStep.name()));
 		
 		// build the step
 		return new StepBuilder().execute(execution, errorHandler).onCallback(resultHandler, errorHandler).getFlowStep();
 	}
 	
 	/**
 	 * a schedule step to repeatly execute something on a customized schedule
 	 * demonstrate how to execute a loop/scheduled task for looping 3 times 
 	 * @return
 	 */
 	public IFlowStep scheduledStep() throws Exception {
 
 		try {
 			final String scheduleName = "Dummy flow session " + this.getKeyOfTarget();
 			ISchedule schedule = SchedulerFactory.getInstance(SchedulerFactory.SCHEDULER_TRANSIENT).createSchedule(scheduleName);
 			schedule.executeRecur(
 					null, 
 					ISchedule.NO_END_DATE, 
 					5, 
 					10
 			);
 			StepExecution execution = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(StepTransition.NOOP) {
 					
 						public StepTransition execute() throws FlowExecutionException {
 							int cnt = sessionContext.getScheduledRunCount();
 							cnt++;
 							sessionContext.setScheduledRunCount(cnt);
 							return (cnt &gt;= 3) ? new StepTransition(steps.stop.name()) : StepTransition.NOOP;
 						}
 						
 			};
 			return new ScheduledStepBuilder()
 						.execute(execution, errorHandler)
 						.schedule(new StepTransition(steps.stop.name()),	schedule)
 						.getFlowStep();
 		} 
 		catch (ScheduleException e) {
 			throw new FlowExecutionException(e);
 		}
 		
 	}
 	
 	/**
 	 * erorr complete step
 	 * @return
 	 */
 	public IFlowStep error() {
 		StepExecution execution = new SimpleStepExecution(
 				new StepTransition().inState(FlowState.Completed).withResult(FlowResult.Failed));
 
 		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
 	}
 	
 	/**
 	 * normal complete step
 	 * @return
 	 */
 	public IFlowStep stop() {
 		StepExecution execution = new SimpleStepExecution(
 				new StepTransition().inState(FlowState.Completed).withResult(FlowResult.Success));
 
 		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
 	}
 	
 	/**
 	 * run a join child session step
 	 * @author biyu
 	 *
 	 */
 	class JoinStepExecution extends AsyncTaskStepExecution&lt;HelloWorldFlowContext&gt; {
 
 		public JoinStepExecution() {
 			super(null, ITaskRunnerKeys.SessionTaskRunner);
 		}
 		
 		private Task buildTask() {
 			FlowJoinTask joinTask = new FlowJoinTask();
 			boolean allSaved = false;
 			try {
 				for (int i = 0; i &lt; 2; i++) {
 					FlowSession child = FlowSessionFactory.getInstance().createChildSession(
 							HelloWorldFlow.class, 
 							new SimpleLocatable(),
 							HelloWorldFlow.this);
 					FlowSessionFactory.getInstance().save(child);
 					joinTask.addSessions(child);
 				}
 				allSaved = true;
 			} catch (FlowInitializationException e) {
 				throw new FlowExecutionException(e);
 			} catch (DataAccessException e) {
 				throw new FlowExecutionException(e);
 			} catch (InvalidObjectException e) {
 				throw new FlowExecutionException(e);
 			} catch (Throwable t) {
 				throw new RuntimeException(t);
 			} finally {
 				if (!allSaved) {
 					joinTask.cancel("Not all child sessions are saved successfully");
 				}
 			}
 			return joinTask;
 		}
 		
 		@Override
 		public StepTransition execute() throws FlowExecutionException {
 			
 			this.task = buildTask();
 			
 			return super.execute();
 		}
 		
 	}
 
 	/**
 	 * customized callback handler for join step
 	 * demonstrate how to do more business logic in handling task result
 	 * @author biyu
 	 *
 	 */
 	static class JoinStepCallbackHandler extends MappedCallbackHandler {
 		
 		public JoinStepCallbackHandler(StepTransition transition) {
 			super(transition);
 		}
 
 		@Override
 		public StepTransition executeOnResult(TaskResult result) throws FlowExecutionException {
 			StepTransition transition = defResult;
 			if (result instanceof FlowTaskResult) {
 				// individual child session completes
 				transition = new StepTransition().withResult(convertStatus(result)).log(result.getMsg());
 			}
 			return transition;
 		}
 
 		@Override
 		public StepTransition executeOnCompleted(TaskResult result) throws FlowExecutionException {
 			String msg = result.getMsg();
 			StepTransition transition = defResult;
 			if (result instanceof FlowJoinTaskResult) {
 				// all child sessions complete
 				if (result.isSuccess()) { // success
 					transition = new StepTransition(steps.scheduledStep.name()).withResult(FlowResult.Success).log(msg);
 				}
 				else { // cancelled, timeout, or failed
 					transition = new StepTransition(steps.error.name()).withResult(FlowResult.Failed).log(msg);
 				}
 			}
@@ -376,5 +378,5 @@
 
 	}
 	
 }
-{code}
+&lt;/code&gt;
&lt;/pre&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Bin Yu</dc:creator><pubDate>Tue, 02 Aug 2011 04:22:27 -0000</pubDate><guid>https://sourceforge.net5f900e1f4fdf002e5e8eb1ac8d58912716d0fbc5</guid></item><item><title>WikiPage workflow modified by Bin Yu</title><link>https://sourceforge.net/p/lightj/wiki/workflow/</link><description>*LightJ embedded workflow engine is a lightweight framework implemented in pure java with no more than 30 core classes, support the following features*

* Persistent or transient state by choice (currently support mysql, oracle, and hsqldb)
* Persistent or transient execution context by choice
* Crash recovery
* Cluster safe (cluster implementation based on shoal/grizzly GMS)
* Built-in synchronous, asynchronous, split/merge, loop, schedule execution pattern support
* Built-in error handling, no error will “fall through the crack”
* Built-in logging and flow event handling
* Many built-in flow fine tune features by annotations.
* Nested flows or flow join support
* Standard flow control interface, start, stop, pause, resume, kill
* Flow validation at initialization, straightforward initialization and registration
* Spring compatible, flow can be initialized by spring DI
* Workflow logic and transition completely built by java, easy to learn, easy to use, easy to support
* Minimal external dependencies, no complicated XML workflow definition in XML

*Key design*

* Workflow implementation by extending FlowSession base class
* FlowDefinition annotation for flow information, and concurrent execution grouping
* FlowStep enum provide state definition of the flow
* Each enum value in FlowStep enum maps to a method in flow implementation using the same name, the method is responsible of building the execution logic for the step
* StepExecution contains execution logic for a flow step, there are 2 main flavors
* StepTransition is returned by a FlowStepExecution and provide information of state transition.
* FlowContext contains context information that can be persisted and accessed each step of the way
* FlowDrive drives the flow from start to end or to as far as it can be run.
* FlowProperty for flow specific properties eg. cluster, recovery, concurrency etc.
* FlowStepProperty annotation for step properties eg. weight
* FlowEvent enum defines flowevent generated by the framework at runtime
* FlowEventListener interface to handle flow event

*Sample session source code*

{code}
package org.lightj.example.session;

import java.io.InvalidObjectException;

import org.lightj.dal.DataAccessException;
import org.lightj.dal.SimpleLocatable;
import org.lightj.schedule.ISchedule;
import org.lightj.schedule.ScheduleException;
import org.lightj.schedule.SchedulerFactory;
import org.lightj.session.FlowDefinition;
import org.lightj.session.FlowExecutionException;
import org.lightj.session.FlowInitializationException;
import org.lightj.session.FlowProperties;
import org.lightj.session.FlowResult;
import org.lightj.session.FlowSession;
import org.lightj.session.FlowSessionFactory;
import org.lightj.session.FlowState;
import org.lightj.session.FlowStepProperties;
import org.lightj.session.step.AsyncTaskStepExecution;
import org.lightj.session.step.IFlowStep;
import org.lightj.session.step.MappedCallbackHandler;
import org.lightj.session.step.MappedErrorHandler;
import org.lightj.session.step.ScheduledStepBuilder;
import org.lightj.session.step.SimpleStepExecution;
import org.lightj.session.step.StepBuilder;
import org.lightj.session.step.StepErrorHandler;
import org.lightj.session.step.StepExecution;
import org.lightj.session.step.StepTransition;
import org.lightj.task.ITaskRunnerKeys;
import org.lightj.task.Task;
import org.lightj.task.TaskResult;
import org.lightj.task.session.FlowJoinTask;
import org.lightj.task.session.FlowJoinTaskResult;
import org.lightj.task.session.FlowTaskResult;


@FlowDefinition(typeId=22, desc="hello world", group="TEST")
@FlowProperties(clusterSafe=true,crashSafe=true)
@SuppressWarnings("unchecked")
public class HelloWorldFlow extends FlowSession&lt;HelloWorldFlowContext&gt; {
	
	public static enum steps {
		@FlowStepProperties(stepWeight=0)
		start,
		@FlowStepProperties(stepWeight=1)
		syncTaskStep,
		@FlowStepProperties(stepWeight=2)
		asyncTaskStep,
		@FlowStepProperties(stepWeight=2)
		splitStep,
		@FlowStepProperties(stepWeight=3)
		forLoopStep,
		@FlowStepProperties(stepWeight=3)
		whileLoopStep,
		@FlowStepProperties(stepWeight=3)
		sessionJoinStep,
		@FlowStepProperties(stepWeight=5)
		scheduledStep,
		@FlowStepProperties(stepWeight=0)
		stop,
		error,
	}

	/**
	 * demonstrate how to do DI for individual step, see {@link HelloWorldFlowStepsImpl}
	 */
	private IFlowStep asyncTaskStep;
	private IFlowStep splitStep;
	private IFlowStep forLoopStep;
	private IFlowStep whileLoopStep;

	public IFlowStep getAsyncTaskStep() {
		return asyncTaskStep;
	}

	public void setAsyncTaskStep(IFlowStep asyncTaskStep) {
		this.asyncTaskStep = asyncTaskStep;
	}

	public IFlowStep getSplitStep() {
		return splitStep;
	}

	public void setSplitStep(IFlowStep slipStep) {
		this.splitStep = slipStep;
	}

	public IFlowStep getForLoopStep() {
		return forLoopStep;
	}

	public void setForLoopStep(IFlowStep forLoopStep) {
		this.forLoopStep = forLoopStep;
	}

	public IFlowStep getWhileLoopStep() {
		return whileLoopStep;
	}

	public void setWhileLoopStep(IFlowStep whileLoopStep) {
		this.whileLoopStep = whileLoopStep;
	}

	public HelloWorldFlow() {
		super();
	}

	@Override
	protected Enum getFirstStepEnum() {
		return steps.start;
	}

	/** shared error handler */
	private StepErrorHandler errorHandler = new MappedErrorHandler(new StepTransition(steps.error));
	
	/**
	 * start step, synchronous
	 * demonstrate how to execute a synchronous step
	 * @return
	 */
	public IFlowStep start() {
		StepExecution execution = new SimpleStepExecution(new StepTransition(getParentId()&gt;0 ? steps.stop : steps.syncTaskStep));

		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
	}
	
	/**
	 * synchronous execution
	 * @return
	 */
	public IFlowStep syncTaskStep() {
		StepExecution execution = new SimpleStepExecution(StepTransition.NOOP) {

			public StepTransition execute() throws FlowExecutionException {
				// do something here
				return new StepTransition(steps.asyncTaskStep);
			}

		};

		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
	}
	
	/**
	 * step to execute a task by task runner
	 * demonstrate how to execute a runtask asynchronous step
	 * @return
	 */
	public IFlowStep asyncTaskStep() 
	{
		return asyncTaskStep;
	}
	
	/**
	 * step to execute a few task in parallel, and merge
	 * @return
	 */
	public IFlowStep splitStep() {
		return splitStep;
	}
	
	/**
	 * step to execute a task in for loop
	 * @return
	 */
	public IFlowStep forLoopStep() {
		return forLoopStep;
	}
	
	/**
	 * step to execute a task in while loop
	 * @return
	 */
	public IFlowStep whileLoopStep() {
		return whileLoopStep;
	}
	
	/**
	 * step to launch child session(s) and join on return
	 * demonstrate how to execute a session join asynchronous task
	 * @return
	 */
	public IFlowStep sessionJoinStep() throws Exception {
		// build execution
		StepExecution execution = new JoinStepExecution();

		// callback handler
		JoinStepCallbackHandler resultHandler = new JoinStepCallbackHandler(
				StepTransition.runToStep(steps.scheduledStep.name()));
		
		// build the step
		return new StepBuilder().execute(execution, errorHandler).onCallback(resultHandler, errorHandler).getFlowStep();
	}
	
	/**
	 * a schedule step to repeatly execute something on a customized schedule
	 * demonstrate how to execute a loop/scheduled task for looping 3 times 
	 * @return
	 */
	public IFlowStep scheduledStep() throws Exception {

		try {
			final String scheduleName = "Dummy flow session " + this.getKeyOfTarget();
			ISchedule schedule = SchedulerFactory.getInstance(SchedulerFactory.SCHEDULER_TRANSIENT).createSchedule(scheduleName);
			schedule.executeRecur(
					null, 
					ISchedule.NO_END_DATE, 
					5, 
					10
			);
			StepExecution execution = new SimpleStepExecution&lt;HelloWorldFlowContext&gt;(StepTransition.NOOP) {
					
						public StepTransition execute() throws FlowExecutionException {
							int cnt = sessionContext.getScheduledRunCount();
							cnt++;
							sessionContext.setScheduledRunCount(cnt);
							return (cnt &gt;= 3) ? new StepTransition(steps.stop.name()) : StepTransition.NOOP;
						}
						
			};
			return new ScheduledStepBuilder()
						.execute(execution, errorHandler)
						.schedule(new StepTransition(steps.stop.name()),	schedule)
						.getFlowStep();
		} 
		catch (ScheduleException e) {
			throw new FlowExecutionException(e);
		}
		
	}
	
	/**
	 * erorr complete step
	 * @return
	 */
	public IFlowStep error() {
		StepExecution execution = new SimpleStepExecution(
				new StepTransition().inState(FlowState.Completed).withResult(FlowResult.Failed));

		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
	}
	
	/**
	 * normal complete step
	 * @return
	 */
	public IFlowStep stop() {
		StepExecution execution = new SimpleStepExecution(
				new StepTransition().inState(FlowState.Completed).withResult(FlowResult.Success));

		return new StepBuilder().execute(execution, errorHandler).getFlowStep();
	}
	
	/**
	 * run a join child session step
	 * @author biyu
	 *
	 */
	class JoinStepExecution extends AsyncTaskStepExecution&lt;HelloWorldFlowContext&gt; {

		public JoinStepExecution() {
			super(null, ITaskRunnerKeys.SessionTaskRunner);
		}
		
		private Task buildTask() {
			FlowJoinTask joinTask = new FlowJoinTask();
			boolean allSaved = false;
			try {
				for (int i = 0; i &lt; 2; i++) {
					FlowSession child = FlowSessionFactory.getInstance().createChildSession(
							HelloWorldFlow.class, 
							new SimpleLocatable(),
							HelloWorldFlow.this);
					FlowSessionFactory.getInstance().save(child);
					joinTask.addSessions(child);
				}
				allSaved = true;
			} catch (FlowInitializationException e) {
				throw new FlowExecutionException(e);
			} catch (DataAccessException e) {
				throw new FlowExecutionException(e);
			} catch (InvalidObjectException e) {
				throw new FlowExecutionException(e);
			} catch (Throwable t) {
				throw new RuntimeException(t);
			} finally {
				if (!allSaved) {
					joinTask.cancel("Not all child sessions are saved successfully");
				}
			}
			return joinTask;
		}
		
		@Override
		public StepTransition execute() throws FlowExecutionException {
			
			this.task = buildTask();
			
			return super.execute();
		}
		
	}

	/**
	 * customized callback handler for join step
	 * demonstrate how to do more business logic in handling task result
	 * @author biyu
	 *
	 */
	static class JoinStepCallbackHandler extends MappedCallbackHandler {
		
		public JoinStepCallbackHandler(StepTransition transition) {
			super(transition);
		}

		@Override
		public StepTransition executeOnResult(TaskResult result) throws FlowExecutionException {
			StepTransition transition = defResult;
			if (result instanceof FlowTaskResult) {
				// individual child session completes
				transition = new StepTransition().withResult(convertStatus(result)).log(result.getMsg());
			}
			return transition;
		}

		@Override
		public StepTransition executeOnCompleted(TaskResult result) throws FlowExecutionException {
			String msg = result.getMsg();
			StepTransition transition = defResult;
			if (result instanceof FlowJoinTaskResult) {
				// all child sessions complete
				if (result.isSuccess()) { // success
					transition = new StepTransition(steps.scheduledStep.name()).withResult(FlowResult.Success).log(msg);
				}
				else { // cancelled, timeout, or failed
					transition = new StepTransition(steps.error.name()).withResult(FlowResult.Failed).log(msg);
				}
			}
			return transition;
		}

	}
	
}
{code}</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Bin Yu</dc:creator><pubDate>Tue, 02 Aug 2011 04:16:18 -0000</pubDate><guid>https://sourceforge.nete967675c946be6435800701955f2d5edbb2d3020</guid></item></channel></rss>