Commits

Anonymous committed 88d3db1

Export from wiki

Comments (0)

Files changed (50)

docs/1. Getting Started.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <p class="paragraph">This section includes a brief overview of the functionality provided by OSWorkflow, as well as instructions on how to configure, deploy, and run the example application and your first workflow.</p><ul><li><a href="1.1 Introduction.html" title="1.1 Introduction">1.1 Introduction</a></li><li><a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li><li><a href="1.3 Running the Example App.html" title="1.3 Running the Example App">1.3 Running the Example App</a></li><li><a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li><li><a href="1.5 Loading Workflow Definitions.html" title="1.5 Loading Workflow Definitions">1.5 Loading Workflow Definitions</a></li></ul>
+				    <p>This section includes a brief overview of the functionality provided by OSWorkflow, as well as instructions on how to configure, deploy, and run the example application and your first workflow.</p>
+
+<ul><li><a href="1.1 Introduction.html" title="1.1 Introduction">1.1 Introduction</a></li><li><a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li><li><a href="1.3 Running the Example App.html" title="1.3 Running the Example App">1.3 Running the Example App</a></li><li><a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li><li><a href="1.5 Loading Workflow Definitions.html" title="1.5 Loading Workflow Definitions">1.5 Loading Workflow Definitions</a></li></ul>
 
                     			    </td>
 		    </tr>

docs/1. Your first workflow - Chinese.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <p class="paragraph">h3 创建描述符</p>首先,让我们来定义工作流。你可以使用任何名字来命名工作流。一个工作流对应一个XML格式的定义文件。让我们来开始新建一个&#147;myworkflow.xml&#148;的文件,这是样板文件:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;&#63;xml version=<span class="xml-quote">&quot;1.0&quot;</span> encoding=<span class="xml-quote">&quot;UTF&#45;8&quot;</span>&#63;&gt;</span>&#10;<span class="xml-tag">&lt;&#33;DOCTYPE workflow PUBLIC &#10;  <span class="xml-quote">&quot;&#45;//OpenSymphony Group//DTD OSWorkflow 2.7//EN&quot;</span>&#10;  <span class="xml-quote">&quot;&#104;ttp://www.opensymphony.com/osworkflow/workflow&#95;2&#95;7.dtd&quot;</span>&gt;</span>&#10;<span class="xml-tag">&lt;workflow&gt;</span>&#10;  <span class="xml-tag">&lt;initial&#45;actions&gt;</span>&#10;    ...&#10;  <span class="xml-tag">&lt;/initial&#45;actions&gt;</span>&#10;  <span class="xml-tag">&lt;steps&gt;</span>&#10;    ...&#10;  <span class="xml-tag">&lt;/steps&gt;</span>&#10;<span class="xml-tag">&lt;/workflow&gt;</span></pre>
-</div></div><p class="paragraph">首先是标准的XML头部,要注意的是OSWorkflow将会通过这些指定的DTD来验证XML内容的合法性。你可以使用绝大多数的XML编辑工具来编辑它,并且可以highlight相应的错误。</p>h3 步骤和动作<p class="paragraph">接下来我们来定义初始化动作和步骤。首先需要理解的OSWorkflow重要概念是steps (步骤) 和 actions (动作)。一个步骤是工作流所处的位置,比如一个简单的工作流过程,它可能从一个步骤流转到另外一个步骤(或者有时候还是停留在一样的步骤)。举例来说,一个文档管理系统的流程,它的步骤名称可能有&#147;First Draft - 草案初稿&#148;,&#147;Edit Stage -编辑阶段&#148;,&#147;At publisher - 出版商&#148;等。</p>动作指定了可能发生在步骤内的转变,通常会导致步骤的变更。在我们的文件管理系统中,在&#147;草案初稿&#148;这个步骤可能有&#147;start first draft - 开始草案初稿&#148;和&#147;complete first draft - 完成草案初稿&#148;这样2个动作。<p class="paragraph">简单的说,步骤是&#147;在哪里&#148;,动作是&#147;可以去哪里&#148;。</p>初始化步骤是一种特殊类型的步骤,它用来启动工作流。在一个工作流程开始前,它是没有状态,不处在任何一个步骤,用户必须采取某些动作才能开始这个流程。这些特殊步骤被定义在 &lt;initial-actions&gt;。<p class="paragraph">在我们的例子里面,假定只有一个简单的初始化步骤:&#147;Start Workflow&#148;,它的定义在里面&lt;initial-actions&gt;:</p><div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start Workflow&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;1&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div><p class="paragraph">这个动作是最简单的类型,只是简单地指明了下一个我们要去的步骤和状态。</p>h3 工作流状态<p class="paragraph">工作流状态是一个用来描述工作流程中具体步骤状态的字符串。在我们的文档管理系统中,在&#147;草案初稿&#148;这个步骤可能有2个不同的状态:&#147;Underway - 进行中&#148;和&#147;Queued - 等候处理中&#148;</p>我们使用&#147;Queued&#148;指明这个条目已经被排入&#147;First Draft&#148;步骤的队列。比如说某人请求编写某篇文档,但是还没有指定作者,那么这个文档在&#147;First Draft&#148;步骤的状态就是&#147;Queued&#148;。&#147;Underway&#148;状态被用来指明一个作者已经挑选了一篇文档开始撰写,而且可能正在锁定这篇文档。<p class="paragraph">h3 第一个步骤</p>让我们来看第一个步骤是怎样被定义在&lt;steps&gt;元素中的。我们有2个动作:第一个动作是保持当前步骤不变,只是改变了状态到&#147;Underway&#148;,第二个动作是移动到工作流的下一步骤。我们来添加如下的内容到&lt;steps&gt;元素:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;step id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;actions&gt;</span>&#10;    <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;results&gt;</span>&#10;        <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> step=<span class="xml-quote">&quot;1&quot;</span>/&gt;</span>&#10;      <span class="xml-tag">&lt;/results&gt;</span>&#10;    <span class="xml-tag">&lt;/action&gt;</span>&#10;    <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;Finish First Draft&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;results&gt;</span>&#10;        <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;2&quot;</span>/&gt;</span>&#10;      <span class="xml-tag">&lt;/results&gt;</span>&#10;    <span class="xml-tag">&lt;/action&gt;</span>&#10;  <span class="xml-tag">&lt;/actions&gt;</span>&#10;<span class="xml-tag">&lt;/step&gt;</span>&#10;<span class="xml-tag">&lt;step id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;finished&quot;</span> /&gt;</span></pre>
-</div></div><p class="paragraph">这样我们就定义了2个动作,old-status属性是用来指明当前步骤完成以后的状态是什么,在大多数的应用中,通常用&quot;Finished&quot;表示。</p>上面定义的这2个动作是没有任何限制的。比如,一个用户可以调用action 2而不用先调用action 1。很明显的,我们如果没有开始撰写草稿,是不可能去完成一个草稿的。同样的,上面的定义也允许你开始撰写草稿多次,这也是毫无意义的。我们也没有做任何的处理去限制其他用户完成别人的草稿。这些都应该需要想办法避免。<p class="paragraph">让我们来一次解决这些问题。首先,我们需要指定只有工作流的状态为&#147;Queued&#148;的时候,一个caller (调用者)才能开始撰写草稿的动作。这样就可以阻止其他用户多次调用开始撰写草稿的动作。我们需要指定动作的约束,约束是由Condition(条件)组成。</p>h3 条件<p class="paragraph">OSWorkflow 有很多有用的内置条件可以使用。在此相关的条件是&#147;StatusCondition - 状态条件&#148;。 条件也可以接受参数,参数的名称通常被定义在javadocs里(如果是使用Java Class实现的条件的话)。在这个例子里面,状态条件接受一个名为&#147;status&#148;的参数,指明了需要检查的状态条件。我们可以从下面的xml定义里面清楚的理解:</p><div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;    <span class="xml-tag">&lt;conditions&gt;</span>&#10;      <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;          com.opensymphony.workflow.util.StatusCondition&#10;        <span class="xml-tag">&lt;/arg&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Queued<span class="xml-tag">&lt;/arg&gt;</span>&#10;      <span class="xml-tag">&lt;/condition&gt;</span>&#10;    <span class="xml-tag">&lt;/conditions&gt;</span>&#10;  <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> step=<span class="xml-quote">&quot;1&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div><p class="paragraph">希望对于条件的理解现在已经清楚了。上面的条件定义保证了动作1只能在当前状态为&#147;Queued&#148;的时候才能被调用,也就是说在初始化动作被调用以后。</p>h3  函数<p class="paragraph">接下来,我们想在一个用户开始撰写草稿以后,设置他为&#147;owner&#148;。为了达到这样的目的,我们需要做2件事情:</p>1) 通过一个函数设置&#147;caller&#148;变量在当前的环境设置里。<br/>
-2) 根据&#147;caller&#148;变量来设置&#147;owner&#148;属性。<p class="paragraph">函数是OSWorkflow的一个功能强大的特性。函数基本上是一个在工作流程中的工作单位,他不会影响到流程本身。举例来说,你可能有一个&#147;SendEmail&#148;的函数,用来在某些特定的流程流转发生时来发送email提醒。</p>函数也可以用来添加变量到当前的环境设置里。变量是一个指定名称的对象,可以用来在工作流中被以后的函数或者脚本使用。<p class="paragraph">OSWorkflow提供了一些内置的常用函数。其中一个称为&#147;Caller&#148;,这个函数会获得当前调用工作流的用户,并把它放入一个名为&#147;caller&#148;的字符型变量中。</p>因为我们需要追踪是哪个用户开始了编写草稿,所以可以使用这个函数来修改我们的动作定义:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;pre&#45;functions&gt;</span>&#10;    <span class="xml-tag">&lt;function type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>com.opensymphony.workflow.util.Caller<span class="xml-tag">&lt;/arg&gt;</span>&#10;    <span class="xml-tag">&lt;/function&gt;</span>&#10;  <span class="xml-tag">&lt;/pre&#45;functions&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> &#10;                                       step=<span class="xml-quote">&quot;1&quot;</span> owner=<span class="xml-quote">&quot;$&#123;caller&#125;&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div><p class="paragraph">h3 组合起来<br/>
-把这些概念都组合起来,这样我们就有了动作1:</p><div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;    <span class="xml-tag">&lt;conditions&gt;</span>&#10;      <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                com.opensymphony.workflow.util.StatusCondition&#10;        <span class="xml-tag">&lt;/arg&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Queued<span class="xml-tag">&lt;/arg&gt;</span>&#10;      <span class="xml-tag">&lt;/condition&gt;</span>&#10;    <span class="xml-tag">&lt;/conditions&gt;</span>&#10;  <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;  <span class="xml-tag">&lt;pre&#45;functions&gt;</span>&#10;    <span class="xml-tag">&lt;function type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;              com.opensymphony.workflow.util.Caller&#10;      <span class="xml-tag">&lt;/arg&gt;</span>&#10;    <span class="xml-tag">&lt;/function&gt;</span>&#10;  <span class="xml-tag">&lt;/pre&#45;functions&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> &#10;                                       step=<span class="xml-quote">&quot;1&quot;</span>  owner=<span class="xml-quote">&quot;$&#123;caller&#125;&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div>
-<p class="paragraph">我们使用类似想法来设置动作2:</p><div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;Finish First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;    <span class="xml-tag">&lt;conditions type=<span class="xml-quote">&quot;AND&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;        <span class="xml-tag">&lt;arg &#10;        name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>com.opensymphony.workflow.util.StatusCondition&#10;        <span class="xml-tag">&lt;/arg&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Underway<span class="xml-tag">&lt;/arg&gt;</span>&#10;      <span class="xml-tag">&lt;/condition&gt;</span>&#10;      <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;              com.opensymphony.workflow.util.AllowOwnerOnlyCondition&#10;       <span class="xml-tag">&lt;/arg&gt;</span>&#10;      <span class="xml-tag">&lt;/condition&gt;</span>&#10;    <span class="xml-tag">&lt;/conditions&gt;</span>&#10;  <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;2&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div><p class="paragraph">在这里我们指定了一个新的条件:&#147;allow owner only&#148;。这样能够保证只有开始撰写这份草稿的用户才能完成它。而状态条件确保了只有在&#147;Underway&#148;状态下的流程才能调用&#147;finish first draft&#148;动作。</p>把他们组合在一起,我们就有了第一个流程定义:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;&#63;xml version=<span class="xml-quote">&quot;1.0&quot;</span> encoding=<span class="xml-quote">&quot;UTF&#45;8&quot;</span>&#63;&gt;</span>&#10;<span class="xml-tag">&lt;&#33;DOCTYPE workflow PUBLIC &#10;                 <span class="xml-quote">&quot;&#45;//OpenSymphony Group//DTD OSWorkflow 2.7//EN&quot;</span>&#10;                 <span class="xml-quote">&quot;&#104;ttp://www.opensymphony.com/osworkflow/workflow&#95;2&#95;7.dtd&quot;</span>&gt;</span>&#10;<span class="xml-tag">&lt;workflow&gt;</span>&#10;  <span class="xml-tag">&lt;initial&#45;actions&gt;</span>&#10;    <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start Workflow&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;results&gt;</span>&#10;        <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;1&quot;</span>/&gt;</span>&#10;      <span class="xml-tag">&lt;/results&gt;</span>&#10;    <span class="xml-tag">&lt;/action&gt;</span>&#10;  <span class="xml-tag">&lt;/initial&#45;actions&gt;</span>&#10;  <span class="xml-tag">&lt;steps&gt;</span>&#10;    <span class="xml-tag">&lt;step id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;First Draft&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;actions&gt;</span>&#10;        <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;          <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;            <span class="xml-tag">&lt;conditions&gt;</span>&#10;              <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                   com.opensymphony.workflow.util.StatusCondition&#10;                <span class="xml-tag">&lt;/arg&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Queued<span class="xml-tag">&lt;/arg&gt;</span>&#10;              <span class="xml-tag">&lt;/condition&gt;</span>&#10;            <span class="xml-tag">&lt;/conditions&gt;</span>&#10;          <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;          <span class="xml-tag">&lt;pre&#45;functions&gt;</span>&#10;            <span class="xml-tag">&lt;function type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;              <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                 com.opensymphony.workflow.util.Caller&#10;              <span class="xml-tag">&lt;/arg&gt;</span>&#10;            <span class="xml-tag">&lt;/function&gt;</span>&#10;          <span class="xml-tag">&lt;/pre&#45;functions&gt;</span>&#10;          <span class="xml-tag">&lt;results&gt;</span>&#10;            <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> &#10;                                           step=<span class="xml-quote">&quot;1&quot;</span>  owner=<span class="xml-quote">&quot;$&#123;caller&#125;&quot;</span>/&gt;</span>&#10;          <span class="xml-tag">&lt;/results&gt;</span>&#10;        <span class="xml-tag">&lt;/action&gt;</span>&#10;        <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;Finish First Draft&quot;</span>&gt;</span>&#10;          <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;            <span class="xml-tag">&lt;conditions type=<span class="xml-quote">&quot;AND&quot;</span>&gt;</span>&#10;              <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                    com.opensymphony.workflow.util.StatusCondition&#10;                <span class="xml-tag">&lt;/arg&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Underway<span class="xml-tag">&lt;/arg&gt;</span>&#10;              <span class="xml-tag">&lt;/condition&gt;</span>&#10;              <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                  com.opensymphony.workflow.util.AllowOwnerOnlyCondition&#10;                <span class="xml-tag">&lt;/arg&gt;</span>&#10;              <span class="xml-tag">&lt;/condition&gt;</span>&#10;            <span class="xml-tag">&lt;/conditions&gt;</span>&#10;          <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;          <span class="xml-tag">&lt;results&gt;</span>&#10;            <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;2&quot;</span>/&gt;</span>&#10;          <span class="xml-tag">&lt;/results&gt;</span>&#10;        <span class="xml-tag">&lt;/action&gt;</span>&#10;      <span class="xml-tag">&lt;/actions&gt;</span>&#10;    <span class="xml-tag">&lt;/step&gt;</span>&#10;    <span class="xml-tag">&lt;step id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;finished&quot;</span> /&gt;</span>&#10;  <span class="xml-tag">&lt;/steps&gt;</span>&#10;<span class="xml-tag">&lt;/workflow&gt;</span></pre>
-</div></div><p class="paragraph">现在这个工作流的定义已经完整了,让我们来测试和检查它的运行。</p>阅读 <a href="2. Testing your workflow - Chinese.html" title="2. Testing your workflow - Chinese">2. Testing your workflow - Chinese</a>.
+				    <p>h3 创建描述符 </p>
+
+<p>首先,让我们来定义工作流。你可以使用任何名字来命名工作流。一个工作流对应一个XML格式的定义文件。让我们来开始新建一个“myworkflow.xml”的文件,这是样板文件:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"UTF-8"</span>?&gt;</span>
+&lt;!DOCTYPE workflow PUBLIC 
+  <span class="code-quote">"-//OpenSymphony Group//DTD OSWorkflow 2.7//EN"</span>
+  <span class="code-quote">"http://www.opensymphony.com/osworkflow/workflow_2_7.dtd"</span>&gt;
+<span class="code-tag">&lt;workflow&gt;</span>
+  <span class="code-tag">&lt;initial-actions&gt;</span>
+    ...
+  <span class="code-tag">&lt;/initial-actions&gt;</span>
+  <span class="code-tag">&lt;steps&gt;</span>
+    ...
+  <span class="code-tag">&lt;/steps&gt;</span>
+<span class="code-tag">&lt;/workflow&gt;</span></pre>
+</div></div>
+
+<p>首先是标准的XML头部,要注意的是OSWorkflow将会通过这些指定的DTD来验证XML内容的合法性。你可以使用绝大多数的XML编辑工具来编辑它,并且可以highlight相应的错误。</p>
+
+<p>h3 步骤和动作</p>
+
+<p>接下来我们来定义初始化动作和步骤。首先需要理解的OSWorkflow重要概念是steps (步骤) 和 actions (动作)。一个步骤是工作流所处的位置,比如一个简单的工作流过程,它可能从一个步骤流转到另外一个步骤(或者有时候还是停留在一样的步骤)。举例来说,一个文档管理系统的流程,它的步骤名称可能有“First Draft - 草案初稿”,“Edit Stage -编辑阶段”,“At publisher - 出版商”等。</p>
+
+<p>动作指定了可能发生在步骤内的转变,通常会导致步骤的变更。在我们的文件管理系统中,在“草案初稿”这个步骤可能有“start first draft - 开始草案初稿”和“complete first draft - 完成草案初稿”这样2个动作。</p>
+
+<p>简单的说,步骤是“在哪里”,动作是“可以去哪里”。</p>
+
+<p>初始化步骤是一种特殊类型的步骤,它用来启动工作流。在一个工作流程开始前,它是没有状态,不处在任何一个步骤,用户必须采取某些动作才能开始这个流程。这些特殊步骤被定义在 &lt;initial-actions&gt;。</p>
+
+<p>在我们的例子里面,假定只有一个简单的初始化步骤:“Start Workflow”,它的定义在里面&lt;initial-actions&gt;:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start Workflow"</span>&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"1"</span>/&gt;</span>
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+<p>这个动作是最简单的类型,只是简单地指明了下一个我们要去的步骤和状态。</p>
+
+<p>h3 工作流状态</p>
+
+<p>工作流状态是一个用来描述工作流程中具体步骤状态的字符串。在我们的文档管理系统中,在“草案初稿”这个步骤可能有2个不同的状态:“Underway - 进行中”和“Queued - 等候处理中”</p>
+
+<p>我们使用“Queued”指明这个条目已经被排入“First Draft”步骤的队列。比如说某人请求编写某篇文档,但是还没有指定作者,那么这个文档在“First Draft”步骤的状态就是“Queued”。“Underway”状态被用来指明一个作者已经挑选了一篇文档开始撰写,而且可能正在锁定这篇文档。</p>
+
+<p>h3 第一个步骤</p>
+
+<p>让我们来看第一个步骤是怎样被定义在&lt;steps&gt;元素中的。我们有2个动作:第一个动作是保持当前步骤不变,只是改变了状态到“Underway”,第二个动作是移动到工作流的下一步骤。我们来添加如下的内容到&lt;steps&gt;元素:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;step id=<span class="code-quote">"1"</span> name=<span class="code-quote">"First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;actions&gt;</span>
+    <span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+      <span class="code-tag">&lt;results&gt;</span>
+        <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> step=<span class="code-quote">"1"</span>/&gt;</span>
+      <span class="code-tag">&lt;/results&gt;</span>
+    <span class="code-tag">&lt;/action&gt;</span>
+    <span class="code-tag">&lt;action id=<span class="code-quote">"2"</span> name=<span class="code-quote">"Finish First Draft"</span>&gt;</span>
+      <span class="code-tag">&lt;results&gt;</span>
+        <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"2"</span>/&gt;</span>
+      <span class="code-tag">&lt;/results&gt;</span>
+    <span class="code-tag">&lt;/action&gt;</span>
+  <span class="code-tag">&lt;/actions&gt;</span>
+<span class="code-tag">&lt;/step&gt;</span>
+<span class="code-tag">&lt;step id=<span class="code-quote">"2"</span> name=<span class="code-quote">"finished"</span> /&gt;</span></pre>
+</div></div>
+
+<p>这样我们就定义了2个动作,old-status属性是用来指明当前步骤完成以后的状态是什么,在大多数的应用中,通常用"Finished"表示。</p>
+
+<p>上面定义的这2个动作是没有任何限制的。比如,一个用户可以调用action 2而不用先调用action 1。很明显的,我们如果没有开始撰写草稿,是不可能去完成一个草稿的。同样的,上面的定义也允许你开始撰写草稿多次,这也是毫无意义的。我们也没有做任何的处理去限制其他用户完成别人的草稿。这些都应该需要想办法避免。</p>
+
+<p>让我们来一次解决这些问题。首先,我们需要指定只有工作流的状态为“Queued”的时候,一个caller (调用者)才能开始撰写草稿的动作。这样就可以阻止其他用户多次调用开始撰写草稿的动作。我们需要指定动作的约束,约束是由Condition(条件)组成。</p>
+
+<p>h3 条件</p>
+
+<p>OSWorkflow 有很多有用的内置条件可以使用。在此相关的条件是“StatusCondition - 状态条件”。 条件也可以接受参数,参数的名称通常被定义在javadocs里(如果是使用Java Class实现的条件的话)。在这个例子里面,状态条件接受一个名为“status”的参数,指明了需要检查的状态条件。我们可以从下面的xml定义里面清楚的理解:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;restrict-to&gt;</span>
+    <span class="code-tag">&lt;conditions&gt;</span>
+      <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+          com.opensymphony.workflow.util.StatusCondition
+        <span class="code-tag">&lt;/arg&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Queued<span class="code-tag">&lt;/arg&gt;</span>
+      <span class="code-tag">&lt;/condition&gt;</span>
+    <span class="code-tag">&lt;/conditions&gt;</span>
+  <span class="code-tag">&lt;/restrict-to&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> step=<span class="code-quote">"1"</span>/&gt;</span>
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+<p>希望对于条件的理解现在已经清楚了。上面的条件定义保证了动作1只能在当前状态为“Queued”的时候才能被调用,也就是说在初始化动作被调用以后。</p>
+
+<p>h3  函数</p>
+
+<p>接下来,我们想在一个用户开始撰写草稿以后,设置他为“owner”。为了达到这样的目的,我们需要做2件事情:</p>
+
+<p>1) 通过一个函数设置“caller”变量在当前的环境设置里。<br/>
+2) 根据“caller”变量来设置“owner”属性。</p>
+
+<p>函数是OSWorkflow的一个功能强大的特性。函数基本上是一个在工作流程中的工作单位,他不会影响到流程本身。举例来说,你可能有一个“SendEmail”的函数,用来在某些特定的流程流转发生时来发送email提醒。</p>
+
+<p>函数也可以用来添加变量到当前的环境设置里。变量是一个指定名称的对象,可以用来在工作流中被以后的函数或者脚本使用。</p>
+
+<p>OSWorkflow提供了一些内置的常用函数。其中一个称为“Caller”,这个函数会获得当前调用工作流的用户,并把它放入一个名为“caller”的字符型变量中。</p>
+
+<p>因为我们需要追踪是哪个用户开始了编写草稿,所以可以使用这个函数来修改我们的动作定义:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;pre-functions&gt;</span>
+    <span class="code-tag">&lt;function type=<span class="code-quote">"class"</span>&gt;</span>
+      <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>com.opensymphony.workflow.util.Caller<span class="code-tag">&lt;/arg&gt;</span>
+    <span class="code-tag">&lt;/function&gt;</span>
+  <span class="code-tag">&lt;/pre-functions&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    &lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> 
+                                       step=<span class="code-quote">"1"</span> owner=<span class="code-quote">"${caller}"</span>/&gt;
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+<p>h3 组合起来<br/>
+把这些概念都组合起来,这样我们就有了动作1:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;restrict-to&gt;</span>
+    <span class="code-tag">&lt;conditions&gt;</span>
+      <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                com.opensymphony.workflow.util.StatusCondition
+        <span class="code-tag">&lt;/arg&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Queued<span class="code-tag">&lt;/arg&gt;</span>
+      <span class="code-tag">&lt;/condition&gt;</span>
+    <span class="code-tag">&lt;/conditions&gt;</span>
+  <span class="code-tag">&lt;/restrict-to&gt;</span>
+  <span class="code-tag">&lt;pre-functions&gt;</span>
+    <span class="code-tag">&lt;function type=<span class="code-quote">"class"</span>&gt;</span>
+      <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+              com.opensymphony.workflow.util.Caller
+      <span class="code-tag">&lt;/arg&gt;</span>
+    <span class="code-tag">&lt;/function&gt;</span>
+  <span class="code-tag">&lt;/pre-functions&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    &lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> 
+                                       step=<span class="code-quote">"1"</span>  owner=<span class="code-quote">"${caller}"</span>/&gt;
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+
+<p>我们使用类似想法来设置动作2:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"2"</span> name=<span class="code-quote">"Finish First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;restrict-to&gt;</span>
+    <span class="code-tag">&lt;conditions type=<span class="code-quote">"AND"</span>&gt;</span>
+      <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+        &lt;arg 
+        name=<span class="code-quote">"class.name"</span>&gt;com.opensymphony.workflow.util.StatusCondition
+        <span class="code-tag">&lt;/arg&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Underway<span class="code-tag">&lt;/arg&gt;</span>
+      <span class="code-tag">&lt;/condition&gt;</span>
+      <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+              com.opensymphony.workflow.util.AllowOwnerOnlyCondition
+       <span class="code-tag">&lt;/arg&gt;</span>
+      <span class="code-tag">&lt;/condition&gt;</span>
+    <span class="code-tag">&lt;/conditions&gt;</span>
+  <span class="code-tag">&lt;/restrict-to&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"2"</span>/&gt;</span>
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+<p>在这里我们指定了一个新的条件:“allow owner only”。这样能够保证只有开始撰写这份草稿的用户才能完成它。而状态条件确保了只有在“Underway”状态下的流程才能调用“finish first draft”动作。</p>
+
+<p>把他们组合在一起,我们就有了第一个流程定义:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"UTF-8"</span>?&gt;</span>
+&lt;!DOCTYPE workflow PUBLIC 
+                 <span class="code-quote">"-//OpenSymphony Group//DTD OSWorkflow 2.7//EN"</span>
+                 <span class="code-quote">"http://www.opensymphony.com/osworkflow/workflow_2_7.dtd"</span>&gt;
+<span class="code-tag">&lt;workflow&gt;</span>
+  <span class="code-tag">&lt;initial-actions&gt;</span>
+    <span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start Workflow"</span>&gt;</span>
+      <span class="code-tag">&lt;results&gt;</span>
+        <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"1"</span>/&gt;</span>
+      <span class="code-tag">&lt;/results&gt;</span>
+    <span class="code-tag">&lt;/action&gt;</span>
+  <span class="code-tag">&lt;/initial-actions&gt;</span>
+  <span class="code-tag">&lt;steps&gt;</span>
+    <span class="code-tag">&lt;step id=<span class="code-quote">"1"</span> name=<span class="code-quote">"First Draft"</span>&gt;</span>
+      <span class="code-tag">&lt;actions&gt;</span>
+        <span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+          <span class="code-tag">&lt;restrict-to&gt;</span>
+            <span class="code-tag">&lt;conditions&gt;</span>
+              <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                   com.opensymphony.workflow.util.StatusCondition
+                <span class="code-tag">&lt;/arg&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Queued<span class="code-tag">&lt;/arg&gt;</span>
+              <span class="code-tag">&lt;/condition&gt;</span>
+            <span class="code-tag">&lt;/conditions&gt;</span>
+          <span class="code-tag">&lt;/restrict-to&gt;</span>
+          <span class="code-tag">&lt;pre-functions&gt;</span>
+            <span class="code-tag">&lt;function type=<span class="code-quote">"class"</span>&gt;</span>
+              <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                 com.opensymphony.workflow.util.Caller
+              <span class="code-tag">&lt;/arg&gt;</span>
+            <span class="code-tag">&lt;/function&gt;</span>
+          <span class="code-tag">&lt;/pre-functions&gt;</span>
+          <span class="code-tag">&lt;results&gt;</span>
+            &lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> 
+                                           step=<span class="code-quote">"1"</span>  owner=<span class="code-quote">"${caller}"</span>/&gt;
+          <span class="code-tag">&lt;/results&gt;</span>
+        <span class="code-tag">&lt;/action&gt;</span>
+        <span class="code-tag">&lt;action id=<span class="code-quote">"2"</span> name=<span class="code-quote">"Finish First Draft"</span>&gt;</span>
+          <span class="code-tag">&lt;restrict-to&gt;</span>
+            <span class="code-tag">&lt;conditions type=<span class="code-quote">"AND"</span>&gt;</span>
+              <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                    com.opensymphony.workflow.util.StatusCondition
+                <span class="code-tag">&lt;/arg&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Underway<span class="code-tag">&lt;/arg&gt;</span>
+              <span class="code-tag">&lt;/condition&gt;</span>
+              <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                  com.opensymphony.workflow.util.AllowOwnerOnlyCondition
+                <span class="code-tag">&lt;/arg&gt;</span>
+              <span class="code-tag">&lt;/condition&gt;</span>
+            <span class="code-tag">&lt;/conditions&gt;</span>
+          <span class="code-tag">&lt;/restrict-to&gt;</span>
+          <span class="code-tag">&lt;results&gt;</span>
+            <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"2"</span>/&gt;</span>
+          <span class="code-tag">&lt;/results&gt;</span>
+        <span class="code-tag">&lt;/action&gt;</span>
+      <span class="code-tag">&lt;/actions&gt;</span>
+    <span class="code-tag">&lt;/step&gt;</span>
+    <span class="code-tag">&lt;step id=<span class="code-quote">"2"</span> name=<span class="code-quote">"finished"</span> /&gt;</span>
+  <span class="code-tag">&lt;/steps&gt;</span>
+<span class="code-tag">&lt;/workflow&gt;</span></pre>
+</div></div>
+
+<p>现在这个工作流的定义已经完整了,让我们来测试和检查它的运行。</p>
+
+<p>阅读 <a href="2. Testing your workflow - Chinese.html" title="2. Testing your workflow - Chinese">2. Testing your workflow - Chinese</a>.</p>
 
                     			    </td>
 		    </tr>

docs/1. Your first workflow.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <p class="paragraph"><h3 style="margin: 4px 0px 4px 0px;" class="heading3"><a name="1.Yourfirstworkflow-Creatingthedescriptor"> Creating the descriptor</a></h3></p>First, let us define the workflow. You can name this workflow whatever you want. Workflow definitions are specified in an XML file, one workflow per file. Let us start by creating a file called &#039;myworkflow.xml&quot;. The boilerplate data for this file is as follows:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;&#63;xml version=<span class="xml-quote">&quot;1.0&quot;</span> encoding=<span class="xml-quote">&quot;UTF&#45;8&quot;</span>&#63;&gt;</span>&#10;<span class="xml-tag">&lt;&#33;DOCTYPE workflow PUBLIC &#10;  <span class="xml-quote">&quot;&#45;//OpenSymphony Group//DTD OSWorkflow 2.7//EN&quot;</span>&#10;  <span class="xml-quote">&quot;&#104;ttp://www.opensymphony.com/osworkflow/workflow&#95;2&#95;7.dtd&quot;</span>&gt;</span>&#10;<span class="xml-tag">&lt;workflow&gt;</span>&#10;  <span class="xml-tag">&lt;initial&#45;actions&gt;</span>&#10;    ...&#10;  <span class="xml-tag">&lt;/initial&#45;actions&gt;</span>&#10;  <span class="xml-tag">&lt;steps&gt;</span>&#10;    ...&#10;  <span class="xml-tag">&lt;/steps&gt;</span>&#10;<span class="xml-tag">&lt;/workflow&gt;</span></pre>
-</div></div><p class="paragraph">We have the standard XML header specified first. Note that OSWorkflow will validate all XML files to the specified DTD, so the workflow definition has to be valid. You can edit it using most XML tools and errors will be highlighted appropriately.</p><h3 class="heading3"><a name="1.Yourfirstworkflow-Stepsandactions"> Steps and actions</a></h3><p class="paragraph">Next we specify initial-actions and steps. The first important concept to understand is that of steps and actions in OSWorkflow. A step is simply a workflow position. As a simple workflow progresses, it moves from one step to another (or even stays in the same step sometimes). As an example, steps names for a document management system would be along the lines of &#039;First Draft&#039;, &#039;Edit Stage&#039;, and &#039;At publisher&quot;.</p>Actions specify the transitions that can take place within a particular step. An action can often result in a change of step. Examples of actions in our document management system would be &#039;start first draft&#039; and &#039;complete first draft&#039; in the &#039;First Draft&#039; step we specified above.<p class="paragraph">Put simply, a step is &#039;where it is&#039;, and an action is &#039;where it can go&#039;.</p>Initial actions are a special type of action that are used to &#039;kick off&#039; the workflow. At the very beginning of a workflow, we have no state, and are not in any step. The user must take some action to start off the process, and this set of possible actions to start the workflow is specified in &lt;initial-actions&gt;.<p class="paragraph">For our example, let us assume that we only have one initial-action, which is simply, &#039;Start Workflow&#039;. Add the following action definition inside of &lt;initial-actions&gt;:</p><div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start Workflow&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;1&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div><p class="paragraph">This action is the simplest possible type of action. It simply specifies the step we move to, as well as what values to set the status to.</p><h3 class="heading3"><a name="1.Yourfirstworkflow-Workflowstatus"> Workflow status</a></h3><p class="paragraph">A workflow status is a string that describes the status of a workflow within a particular step. In our document management system, our &#039;First Draft&#039; step might have two disinct statuses, &#039;Underway&#039;, and &#039;Queued&#039; that it cares about.</p>We use &#039;Queued&#039; to denote that the item has been queued in the &#039;First Draft&#039;. Let&#039;s say someone has requested that a particular document be written, but no author has been assigned. So the document is now currently &#039;Queued&#039; in the &#039;First Draft&#039; step. The &#039;Underway&#039; status would be used to denote that an author has picked the document from the queue and perhaps locked it, denoting that he is now working on the first draft.<p class="paragraph"><h3 class="heading3"><a name="1.Yourfirstworkflow-Thefirststep"> The first step</a></h3></p>Let us examine how that first step would be defined in our &lt;steps&gt; element. We know we have two actions. The first of these actions (start first draft) keeps us in the same step, but changes the status to &#039;Underway&#039;. The second action moves us to the next step in the workflow, which in this case is a &#039;finished&#039; step, for the sake of simplicity. So we now add the following inside our &lt;steps&gt; element:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;step id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;actions&gt;</span>&#10;    <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;results&gt;</span>&#10;        <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> step=<span class="xml-quote">&quot;1&quot;</span>/&gt;</span>&#10;      <span class="xml-tag">&lt;/results&gt;</span>&#10;    <span class="xml-tag">&lt;/action&gt;</span>&#10;    <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;Finish First Draft&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;results&gt;</span>&#10;        <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;2&quot;</span>/&gt;</span>&#10;      <span class="xml-tag">&lt;/results&gt;</span>&#10;    <span class="xml-tag">&lt;/action&gt;</span>&#10;  <span class="xml-tag">&lt;/actions&gt;</span>&#10;<span class="xml-tag">&lt;/step&gt;</span>&#10;<span class="xml-tag">&lt;step id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;finished&quot;</span> /&gt;</span></pre>
-</div></div><p class="paragraph">Above we see the two actions defined. The old-status attribute is used to denote what should be entered in the history table for the current state to denote that it has been completed. In almost all cases, this will be &#039;Finished&#039;.</p>The actions as specified above are of limited use. For example, it is possible for a user to call action 2 without first having called action 1. Clearly, it should not be possible to finish a draft that has yet to be started. Similarly, it is possible to also start the first draft multiple times, which also makes no sense. Finally, we also<br/>
-have nothing in place to stop a second user cannot from finishing first user&#039;s draft. This is also something we&#039;d like to avoid.<p class="paragraph">Let us tackle these problems one at a time. First, we&#039;d like to specify that a caller can only start a first draft when the workflow is in the &#039;Queued&#039; state. This would stop users from being able to start the first draft multiple times. To do so, we specify a restriction on the action. The restriction consists of a condition.</p><h3 class="heading3"><a name="1.Yourfirstworkflow-Conditions"> Conditions</a></h3><p class="paragraph">OSWorkflow has a number of useful built-in conditions that can be used. The relevant condition in this case &#039;StatusCondition&#039;. Conditions can also accept arguments, which are usually specified in the javadocs for a particular condition (if it is a condition implemented as a java class). In this case for example, the status condition takes an argument called &#039;status&#039; which specifies the status to check in order for the condition to pass. This idea becomes much clearer if we examine the XML required to specify this condition:</p><div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;    <span class="xml-tag">&lt;conditions&gt;</span>&#10;      <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;          com.opensymphony.workflow.util.StatusCondition&#10;        <span class="xml-tag">&lt;/arg&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Queued<span class="xml-tag">&lt;/arg&gt;</span>&#10;      <span class="xml-tag">&lt;/condition&gt;</span>&#10;    <span class="xml-tag">&lt;/conditions&gt;</span>&#10;  <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> step=<span class="xml-quote">&quot;1&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div><p class="paragraph">Hopefully the ides of conditions is clearer now. The above condition ensures that action 1 can only be invoked if the current status is &#039;Queued&#039;, which it only ever is right after our initial action has been called.</p><h3 class="heading3"><a name="1.Yourfirstworkflow-Functions"> Functions</a></h3><p class="paragraph">Next, we&#039;d like to specify that when a user starts the first draft, they become the &#039;owner&#039;. To do this, we need a couple of things:</p>1) A function that places a &#039;caller&#039; variable in the current context.<br/>
-2) Setting the &#039;owner&#039; attribute of the result to that &#039;caller&#039; variable.<p class="paragraph">Functions are a powerful feature of OSWorkflow. A function is basically a unit of work that can be performed during a workflow transition, that does not affect the workflow itself. For example, you could have a &#039;SendEmail&#039; function that is responsible for sending out an email notification when a particular transition takes place.</p>Functions can also add variables to the current context. A variable is a named object that is made available to the workflow and can be referenced later on by other functions or scripts.<p class="paragraph">OSWorkflow comes with a number of useful built-in functions. One of these functions is the &#039;Caller&#039; function. This function looks up the current user invoking the workflow, and exposes a named variable called &#039;caller&#039; that is the string<br/>
-value of the calling user.</p>Since we&#039;d like to keep track of who started our first draft, we would use this function by modifying our action as follows:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;pre&#45;functions&gt;</span>&#10;    <span class="xml-tag">&lt;function type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>com.opensymphony.workflow.util.Caller<span class="xml-tag">&lt;/arg&gt;</span>&#10;    <span class="xml-tag">&lt;/function&gt;</span>&#10;  <span class="xml-tag">&lt;/pre&#45;functions&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> &#10;                                       step=<span class="xml-quote">&quot;1&quot;</span> owner=<span class="xml-quote">&quot;$&#123;caller&#125;&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div><p class="paragraph"><h3 class="heading3"><a name="1.Yourfirstworkflow-Puttingitalltogether"> Putting it all together</a></h3></p>Putting the ideas above together, we now have the following definition for action 1:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;    <span class="xml-tag">&lt;conditions&gt;</span>&#10;      <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                com.opensymphony.workflow.util.StatusCondition&#10;        <span class="xml-tag">&lt;/arg&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Queued<span class="xml-tag">&lt;/arg&gt;</span>&#10;      <span class="xml-tag">&lt;/condition&gt;</span>&#10;    <span class="xml-tag">&lt;/conditions&gt;</span>&#10;  <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;  <span class="xml-tag">&lt;pre&#45;functions&gt;</span>&#10;    <span class="xml-tag">&lt;function type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;              com.opensymphony.workflow.util.Caller&#10;      <span class="xml-tag">&lt;/arg&gt;</span>&#10;    <span class="xml-tag">&lt;/function&gt;</span>&#10;  <span class="xml-tag">&lt;/pre&#45;functions&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> &#10;                                       step=<span class="xml-quote">&quot;1&quot;</span>  owner=<span class="xml-quote">&quot;$&#123;caller&#125;&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div>
-<p class="paragraph">We use the same ideas when defining action 2:</p><div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;Finish First Draft&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;    <span class="xml-tag">&lt;conditions type=<span class="xml-quote">&quot;AND&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;        <span class="xml-tag">&lt;arg &#10;        name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>com.opensymphony.workflow.util.StatusCondition&#10;        <span class="xml-tag">&lt;/arg&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Underway<span class="xml-tag">&lt;/arg&gt;</span>&#10;      <span class="xml-tag">&lt;/condition&gt;</span>&#10;      <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;        <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;              com.opensymphony.workflow.util.AllowOwnerOnlyCondition&#10;       <span class="xml-tag">&lt;/arg&gt;</span>&#10;      <span class="xml-tag">&lt;/condition&gt;</span>&#10;    <span class="xml-tag">&lt;/conditions&gt;</span>&#10;  <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;  <span class="xml-tag">&lt;results&gt;</span>&#10;    <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;2&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;/results&gt;</span>&#10;<span class="xml-tag">&lt;/action&gt;</span></pre>
-</div></div><p class="paragraph">Here we specify a new condition, the &#039;allow ownly only&#039; condition. This ensures that only the user that started the first draft can finish it (which we specified in the previous result&#039;s owner attribute). The status condition likewise ensures that the &#039;finish first draft&#039; action can only be performed when the status is &#039;Underway&#039;, which happens only after a user has started the first draft.</p>Putting it all together, we have our complete workflow definition below:<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;&#63;xml version=<span class="xml-quote">&quot;1.0&quot;</span> encoding=<span class="xml-quote">&quot;UTF&#45;8&quot;</span>&#63;&gt;</span>&#10;<span class="xml-tag">&lt;&#33;DOCTYPE workflow PUBLIC &#10;                 <span class="xml-quote">&quot;&#45;//OpenSymphony Group//DTD OSWorkflow 2.7//EN&quot;</span>&#10;                 <span class="xml-quote">&quot;&#104;ttp://www.opensymphony.com/osworkflow/workflow&#95;2&#95;7.dtd&quot;</span>&gt;</span>&#10;<span class="xml-tag">&lt;workflow&gt;</span>&#10;  <span class="xml-tag">&lt;initial&#45;actions&gt;</span>&#10;    <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start Workflow&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;results&gt;</span>&#10;        <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;1&quot;</span>/&gt;</span>&#10;      <span class="xml-tag">&lt;/results&gt;</span>&#10;    <span class="xml-tag">&lt;/action&gt;</span>&#10;  <span class="xml-tag">&lt;/initial&#45;actions&gt;</span>&#10;  <span class="xml-tag">&lt;steps&gt;</span>&#10;    <span class="xml-tag">&lt;step id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;First Draft&quot;</span>&gt;</span>&#10;      <span class="xml-tag">&lt;actions&gt;</span>&#10;        <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;1&quot;</span> name=<span class="xml-quote">&quot;Start First Draft&quot;</span>&gt;</span>&#10;          <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;            <span class="xml-tag">&lt;conditions&gt;</span>&#10;              <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                   com.opensymphony.workflow.util.StatusCondition&#10;                <span class="xml-tag">&lt;/arg&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Queued<span class="xml-tag">&lt;/arg&gt;</span>&#10;              <span class="xml-tag">&lt;/condition&gt;</span>&#10;            <span class="xml-tag">&lt;/conditions&gt;</span>&#10;          <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;          <span class="xml-tag">&lt;pre&#45;functions&gt;</span>&#10;            <span class="xml-tag">&lt;function type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;              <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                 com.opensymphony.workflow.util.Caller&#10;              <span class="xml-tag">&lt;/arg&gt;</span>&#10;            <span class="xml-tag">&lt;/function&gt;</span>&#10;          <span class="xml-tag">&lt;/pre&#45;functions&gt;</span>&#10;          <span class="xml-tag">&lt;results&gt;</span>&#10;            <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Underway&quot;</span> &#10;                                           step=<span class="xml-quote">&quot;1&quot;</span>  owner=<span class="xml-quote">&quot;$&#123;caller&#125;&quot;</span>/&gt;</span>&#10;          <span class="xml-tag">&lt;/results&gt;</span>&#10;        <span class="xml-tag">&lt;/action&gt;</span>&#10;        <span class="xml-tag">&lt;action id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;Finish First Draft&quot;</span>&gt;</span>&#10;          <span class="xml-tag">&lt;restrict&#45;to&gt;</span>&#10;            <span class="xml-tag">&lt;conditions type=<span class="xml-quote">&quot;AND&quot;</span>&gt;</span>&#10;              <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                    com.opensymphony.workflow.util.StatusCondition&#10;                <span class="xml-tag">&lt;/arg&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;status&quot;</span>&gt;</span>Underway<span class="xml-tag">&lt;/arg&gt;</span>&#10;              <span class="xml-tag">&lt;/condition&gt;</span>&#10;              <span class="xml-tag">&lt;condition type=<span class="xml-quote">&quot;class&quot;</span>&gt;</span>&#10;                <span class="xml-tag">&lt;arg name=<span class="xml-quote">&quot;class.name&quot;</span>&gt;</span>&#10;                  com.opensymphony.workflow.util.AllowOwnerOnlyCondition&#10;                <span class="xml-tag">&lt;/arg&gt;</span>&#10;              <span class="xml-tag">&lt;/condition&gt;</span>&#10;            <span class="xml-tag">&lt;/conditions&gt;</span>&#10;          <span class="xml-tag">&lt;/restrict&#45;to&gt;</span>&#10;          <span class="xml-tag">&lt;results&gt;</span>&#10;            <span class="xml-tag">&lt;unconditional&#45;result old&#45;status=<span class="xml-quote">&quot;Finished&quot;</span> status=<span class="xml-quote">&quot;Queued&quot;</span> step=<span class="xml-quote">&quot;2&quot;</span>/&gt;</span>&#10;          <span class="xml-tag">&lt;/results&gt;</span>&#10;        <span class="xml-tag">&lt;/action&gt;</span>&#10;      <span class="xml-tag">&lt;/actions&gt;</span>&#10;    <span class="xml-tag">&lt;/step&gt;</span>&#10;    <span class="xml-tag">&lt;step id=<span class="xml-quote">&quot;2&quot;</span> name=<span class="xml-quote">&quot;finished&quot;</span> /&gt;</span>&#10;  <span class="xml-tag">&lt;/steps&gt;</span>&#10;<span class="xml-tag">&lt;/workflow&gt;</span></pre>
-</div></div><p class="paragraph">Now that the workflow definition is complete, it&#039;s time to test it and verify its behaviour.</p>Go to <a href="2. Testing your workflow.html" title="2. Testing your workflow">2. Testing your workflow</a>.
+				    <h3><a name="1.Yourfirstworkflow-Creatingthedescriptor">Creating the descriptor</a></h3>
+
+<p>First, let us define the workflow. You can name this workflow whatever you want. Workflow definitions are specified in an XML file, one workflow per file. Let us start by creating a file called 'myworkflow.xml". The boilerplate data for this file is as follows:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"UTF-8"</span>?&gt;</span>
+&lt;!DOCTYPE workflow PUBLIC 
+  <span class="code-quote">"-//OpenSymphony Group//DTD OSWorkflow 2.8//EN"</span>
+  <span class="code-quote">"http://www.opensymphony.com/osworkflow/workflow_2_8.dtd"</span>&gt;
+<span class="code-tag">&lt;workflow&gt;</span>
+  <span class="code-tag">&lt;initial-actions&gt;</span>
+    ...
+  <span class="code-tag">&lt;/initial-actions&gt;</span>
+  <span class="code-tag">&lt;steps&gt;</span>
+    ...
+  <span class="code-tag">&lt;/steps&gt;</span>
+<span class="code-tag">&lt;/workflow&gt;</span></pre>
+</div></div>
+
+<p>We have the standard XML header specified first. Note that OSWorkflow will validate all XML files to the specified DTD, so the workflow definition has to be valid. You can edit it using most XML tools and errors will be highlighted appropriately.</p>
+
+<h3><a name="1.Yourfirstworkflow-Stepsandactions">Steps and actions</a></h3>
+
+<p>Next we specify initial-actions and steps. The first important concept to understand is that of steps and actions in OSWorkflow. A step is simply a workflow position. As a simple workflow progresses, it moves from one step to another (or even stays in the same step sometimes). As an example, steps names for a document management system would be along the lines of 'First Draft', 'Edit Stage', and 'At publisher".</p>
+
+<p>Actions specify the transitions that can take place within a particular step. An action can often result in a change of step. Examples of actions in our document management system would be 'start first draft' and 'complete first draft' in the 'First Draft' step we specified above.</p>
+
+<p>Put simply, a step is 'where it is', and an action is 'where it can go'.</p>
+
+<p>Initial actions are a special type of action that are used to 'kick off' the workflow. At the very beginning of a workflow, we have no state, and are not in any step. The user must take some action to start off the process, and this set of possible actions to start the workflow is specified in &lt;initial-actions&gt;.</p>
+
+<p>For our example, let us assume that we only have one initial-action, which is simply, 'Start Workflow'. Add the following action definition inside of &lt;initial-actions&gt;:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start Workflow"</span>&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"1"</span>/&gt;</span>
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+<p>This action is the simplest possible type of action. It simply specifies the step we move to, as well as what values to set the status to.</p>
+
+<h3><a name="1.Yourfirstworkflow-Workflowstatus">Workflow status</a></h3>
+
+<p>A workflow status is a string that describes the status of a workflow within a particular step. In our document management system, our 'First Draft' step might have two disinct statuses, 'Underway', and 'Queued' that it cares about.</p>
+
+<p>We use 'Queued' to denote that the item has been queued in the 'First Draft'. Let's say someone has requested that a particular document be written, but no author has been assigned. So the document is now currently 'Queued' in the 'First Draft' step. The 'Underway' status would be used to denote that an author has picked the document from the queue and perhaps locked it, denoting that he is now working on the first draft.</p>
+
+<h3><a name="1.Yourfirstworkflow-Thefirststep">The first step</a></h3>
+
+<p>Let us examine how that first step would be defined in our &lt;steps&gt; element. We know we have two actions. The first of these actions (start first draft) keeps us in the same step, but changes the status to 'Underway'. The second action moves us to the next step in the workflow, which in this case is a 'finished' step, for the sake of simplicity. So we now add the following inside our &lt;steps&gt; element:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;step id=<span class="code-quote">"1"</span> name=<span class="code-quote">"First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;actions&gt;</span>
+    <span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+      <span class="code-tag">&lt;results&gt;</span>
+        <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> step=<span class="code-quote">"1"</span>/&gt;</span>
+      <span class="code-tag">&lt;/results&gt;</span>
+    <span class="code-tag">&lt;/action&gt;</span>
+    <span class="code-tag">&lt;action id=<span class="code-quote">"2"</span> name=<span class="code-quote">"Finish First Draft"</span>&gt;</span>
+      <span class="code-tag">&lt;results&gt;</span>
+        <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"2"</span>/&gt;</span>
+      <span class="code-tag">&lt;/results&gt;</span>
+    <span class="code-tag">&lt;/action&gt;</span>
+  <span class="code-tag">&lt;/actions&gt;</span>
+<span class="code-tag">&lt;/step&gt;</span>
+<span class="code-tag">&lt;step id=<span class="code-quote">"2"</span> name=<span class="code-quote">"finished"</span> /&gt;</span></pre>
+</div></div>
+
+<p>Above we see the two actions defined. The old-status attribute is used to denote what should be entered in the history table for the current state to denote that it has been completed. In almost all cases, this will be 'Finished'.</p>
+
+<p>The actions as specified above are of limited use. For example, it is possible for a user to call action 2 without first having called action 1. Clearly, it should not be possible to finish a draft that has yet to be started. Similarly, it is possible to also start the first draft multiple times, which also makes no sense. Finally, we also<br/>
+have nothing in place to stop a second user cannot from finishing first user's draft. This is also something we'd like to avoid.</p>
+
+<p>Let us tackle these problems one at a time. First, we'd like to specify that a caller can only start a first draft when the workflow is in the 'Queued' state. This would stop users from being able to start the first draft multiple times. To do so, we specify a restriction on the action. The restriction consists of a condition. </p>
+
+<h3><a name="1.Yourfirstworkflow-Conditions">Conditions</a></h3>
+
+<p>OSWorkflow has a number of useful built-in conditions that can be used. The relevant condition in this case 'StatusCondition'. Conditions can also accept arguments, which are usually specified in the javadocs for a particular condition (if it is a condition implemented as a java class). </p>
+
+<p>A condition, like functions and other base constructs, can be implemented in a variety of ways, including beanshell scripts, or java classes that implement the Condition interface.</p>
+
+<p>In this case for example, we use the status condition class. The status condition takes an argument called 'status' which specifies the status to check in order for the condition to pass. This idea becomes much clearer if we examine the XML required to specify this condition:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;restrict-to&gt;</span>
+    <span class="code-tag">&lt;conditions&gt;</span>
+      <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+          com.opensymphony.workflow.util.StatusCondition
+        <span class="code-tag">&lt;/arg&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Queued<span class="code-tag">&lt;/arg&gt;</span>
+      <span class="code-tag">&lt;/condition&gt;</span>
+    <span class="code-tag">&lt;/conditions&gt;</span>
+  <span class="code-tag">&lt;/restrict-to&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> step=<span class="code-quote">"1"</span>/&gt;</span>
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+<p>Hopefully the idea of conditions is clearer now. The above condition ensures that action 1 can only be invoked if the current status is 'Queued', which it only ever is right after our initial action has been called.</p>
+
+<h3><a name="1.Yourfirstworkflow-Functions">Functions</a></h3>
+
+<p>Next, we'd like to specify that when a user starts the first draft, they become the 'owner'. To do this, we need a couple of things:</p>
+
+<p>1) A function that places a 'caller' variable in the current context.<br/>
+2) Setting the 'owner' attribute of the result to that 'caller' variable.</p>
+
+<p>Functions are a powerful feature of OSWorkflow. A function is basically a unit of work that can be performed during a workflow transition, that does not affect the workflow itself. For example, you could have a 'SendEmail' function that is responsible for sending out an email notification when a particular transition takes place.</p>
+
+<p>Functions can also add variables to the current context. A variable is a named object that is made available to the workflow and can be referenced later on by other functions or scripts.</p>
+
+<p>OSWorkflow comes with a number of useful built-in functions. One of these functions is the 'Caller' function. This function looks up the current user invoking the workflow, and exposes a named variable called 'caller' that is the string<br/>
+value of the calling user.</p>
+
+<p>Since we'd like to keep track of who started our first draft, we would use this function by modifying our action as follows:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;pre-functions&gt;</span>
+    <span class="code-tag">&lt;function type=<span class="code-quote">"class"</span>&gt;</span>
+      <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>com.opensymphony.workflow.util.Caller<span class="code-tag">&lt;/arg&gt;</span>
+    <span class="code-tag">&lt;/function&gt;</span>
+  <span class="code-tag">&lt;/pre-functions&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    &lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> 
+                                       step=<span class="code-quote">"1"</span> owner=<span class="code-quote">"${caller}"</span>/&gt;
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+<h3><a name="1.Yourfirstworkflow-Puttingitalltogether">Putting it all together</a></h3>
+
+<p>Putting the ideas above together, we now have the following definition for action 1:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;restrict-to&gt;</span>
+    <span class="code-tag">&lt;conditions&gt;</span>
+      <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                com.opensymphony.workflow.util.StatusCondition
+        <span class="code-tag">&lt;/arg&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Queued<span class="code-tag">&lt;/arg&gt;</span>
+      <span class="code-tag">&lt;/condition&gt;</span>
+    <span class="code-tag">&lt;/conditions&gt;</span>
+  <span class="code-tag">&lt;/restrict-to&gt;</span>
+  <span class="code-tag">&lt;pre-functions&gt;</span>
+    <span class="code-tag">&lt;function type=<span class="code-quote">"class"</span>&gt;</span>
+      <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+              com.opensymphony.workflow.util.Caller
+      <span class="code-tag">&lt;/arg&gt;</span>
+    <span class="code-tag">&lt;/function&gt;</span>
+  <span class="code-tag">&lt;/pre-functions&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    &lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> 
+                                       step=<span class="code-quote">"1"</span>  owner=<span class="code-quote">"${caller}"</span>/&gt;
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+
+<p>We use the same ideas when defining action 2:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;action id=<span class="code-quote">"2"</span> name=<span class="code-quote">"Finish First Draft"</span>&gt;</span>
+  <span class="code-tag">&lt;restrict-to&gt;</span>
+    <span class="code-tag">&lt;conditions type=<span class="code-quote">"AND"</span>&gt;</span>
+      <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+        &lt;arg 
+        name=<span class="code-quote">"class.name"</span>&gt;com.opensymphony.workflow.util.StatusCondition
+        <span class="code-tag">&lt;/arg&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Underway<span class="code-tag">&lt;/arg&gt;</span>
+      <span class="code-tag">&lt;/condition&gt;</span>
+      <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+        <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+              com.opensymphony.workflow.util.AllowOwnerOnlyCondition
+       <span class="code-tag">&lt;/arg&gt;</span>
+      <span class="code-tag">&lt;/condition&gt;</span>
+    <span class="code-tag">&lt;/conditions&gt;</span>
+  <span class="code-tag">&lt;/restrict-to&gt;</span>
+  <span class="code-tag">&lt;results&gt;</span>
+    <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"2"</span>/&gt;</span>
+  <span class="code-tag">&lt;/results&gt;</span>
+<span class="code-tag">&lt;/action&gt;</span></pre>
+</div></div>
+
+<p>Here we specify a new condition, the 'allow owner only' condition. This ensures that only the user that started the first draft can finish it (which we specified in the previous result's owner attribute). The status condition likewise ensures that the 'finish first draft' action can only be performed when the status is 'Underway', which happens only after a user has started the first draft.</p>
+
+<p>Putting it all together, we have our complete workflow definition below:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;?xml version=<span class="code-quote">"1.0"</span> encoding=<span class="code-quote">"UTF-8"</span>?&gt;</span>
+&lt;!DOCTYPE workflow PUBLIC 
+                 <span class="code-quote">"-//OpenSymphony Group//DTD OSWorkflow 2.8//EN"</span>
+                 <span class="code-quote">"http://www.opensymphony.com/osworkflow/workflow_2_8.dtd"</span>&gt;
+<span class="code-tag">&lt;workflow&gt;</span>
+  <span class="code-tag">&lt;initial-actions&gt;</span>
+    <span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start Workflow"</span>&gt;</span>
+      <span class="code-tag">&lt;results&gt;</span>
+        <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"1"</span>/&gt;</span>
+      <span class="code-tag">&lt;/results&gt;</span>
+    <span class="code-tag">&lt;/action&gt;</span>
+  <span class="code-tag">&lt;/initial-actions&gt;</span>
+  <span class="code-tag">&lt;steps&gt;</span>
+    <span class="code-tag">&lt;step id=<span class="code-quote">"1"</span> name=<span class="code-quote">"First Draft"</span>&gt;</span>
+      <span class="code-tag">&lt;actions&gt;</span>
+        <span class="code-tag">&lt;action id=<span class="code-quote">"1"</span> name=<span class="code-quote">"Start First Draft"</span>&gt;</span>
+          <span class="code-tag">&lt;restrict-to&gt;</span>
+            <span class="code-tag">&lt;conditions&gt;</span>
+              <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                   com.opensymphony.workflow.util.StatusCondition
+                <span class="code-tag">&lt;/arg&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Queued<span class="code-tag">&lt;/arg&gt;</span>
+              <span class="code-tag">&lt;/condition&gt;</span>
+            <span class="code-tag">&lt;/conditions&gt;</span>
+          <span class="code-tag">&lt;/restrict-to&gt;</span>
+          <span class="code-tag">&lt;pre-functions&gt;</span>
+            <span class="code-tag">&lt;function type=<span class="code-quote">"class"</span>&gt;</span>
+              <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                 com.opensymphony.workflow.util.Caller
+              <span class="code-tag">&lt;/arg&gt;</span>
+            <span class="code-tag">&lt;/function&gt;</span>
+          <span class="code-tag">&lt;/pre-functions&gt;</span>
+          <span class="code-tag">&lt;results&gt;</span>
+            &lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Underway"</span> 
+                                           step=<span class="code-quote">"1"</span>  owner=<span class="code-quote">"${caller}"</span>/&gt;
+          <span class="code-tag">&lt;/results&gt;</span>
+        <span class="code-tag">&lt;/action&gt;</span>
+        <span class="code-tag">&lt;action id=<span class="code-quote">"2"</span> name=<span class="code-quote">"Finish First Draft"</span>&gt;</span>
+          <span class="code-tag">&lt;restrict-to&gt;</span>
+            <span class="code-tag">&lt;conditions type=<span class="code-quote">"AND"</span>&gt;</span>
+              <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                    com.opensymphony.workflow.util.StatusCondition
+                <span class="code-tag">&lt;/arg&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"status"</span>&gt;</span>Underway<span class="code-tag">&lt;/arg&gt;</span>
+              <span class="code-tag">&lt;/condition&gt;</span>
+              <span class="code-tag">&lt;condition type=<span class="code-quote">"class"</span>&gt;</span>
+                <span class="code-tag">&lt;arg name=<span class="code-quote">"class.name"</span>&gt;</span>
+                  com.opensymphony.workflow.util.AllowOwnerOnlyCondition
+                <span class="code-tag">&lt;/arg&gt;</span>
+              <span class="code-tag">&lt;/condition&gt;</span>
+            <span class="code-tag">&lt;/conditions&gt;</span>
+          <span class="code-tag">&lt;/restrict-to&gt;</span>
+          <span class="code-tag">&lt;results&gt;</span>
+            <span class="code-tag">&lt;unconditional-result old-status=<span class="code-quote">"Finished"</span> status=<span class="code-quote">"Queued"</span> step=<span class="code-quote">"2"</span>/&gt;</span>
+          <span class="code-tag">&lt;/results&gt;</span>
+        <span class="code-tag">&lt;/action&gt;</span>
+      <span class="code-tag">&lt;/actions&gt;</span>
+    <span class="code-tag">&lt;/step&gt;</span>
+    <span class="code-tag">&lt;step id=<span class="code-quote">"2"</span> name=<span class="code-quote">"finished"</span> /&gt;</span>
+  <span class="code-tag">&lt;/steps&gt;</span>
+<span class="code-tag">&lt;/workflow&gt;</span></pre>
+</div></div>
+
+<p>Now that the workflow definition is complete, it's time to test it and verify its behaviour.</p>
+
+<p>Go to <a href="2. Testing your workflow.html" title="2. Testing your workflow">2. Testing your workflow</a>.</p>
 
                     			    </td>
 		    </tr>

docs/1.1 Introduction.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <ul class="star">
-<li> Forward to <a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li>
-</ul><br/>
-OSWorkflow is fairly different from most other workflow systems available, both commercially and in the open source world. What makes OSWorkflow different is that it is extremely flexible. This can be hard to grasp at first, however. For example, OSWorkflow does not mandate a graphical tool for developing workflows, and the recommended approach is to write the xml workflow descriptors &#039;by hand&#039;. It is up to the application developer to provide this sort of integration, as well as any integration with existing code and databases. These may seem like problems to someone who is looking for a quick &quot;plug-and-play&quot; workflow solution, but we&#039;ve found that such a solution never provides enough flexibility to properly fulfill all requirements in a full-blown application. <p class="paragraph"><b class="strong">OSWorkflow gives you this flexibility</b>.</p>OSWorkflow can be considered a &quot;low level&quot; workflow implementation. Situations like &quot;loops&quot; and &quot;conditions&quot; that might be represented by a graphical icon in other workflow systems must be &quot;coded&quot; in OSWorkflow. That&#039;s not to say that actual code is needed to implement situations like this, but a scripting language must be employed to specify these conditions. It is not expected that a non-technical user modify workflow. We&#039;ve found that although some systems provide GUIs that allow for simple editing of workflows, the applications surrounding the workflow usually end up damaged when changes like these are made. We believe it is best for these changes to be made by a developer who is aware of each change. Having said that, the latest version provides a GUI designer that can help with the editing of the workflow.<p class="paragraph">OSWorkflow is based heavily on the concept of the <em class="emphasis">finite state machine</em>. Each state in represented by the combination of a step ID and a status. A <b class="strong">transition</b> from one state to another cannot happen without an action occuring first. There are always at least one or more active states during the lifetime of a workflow. These simple concepts are what lie at the core of the OSWorkflow engine and allow a simple XML file to be translated in to business workflow processes.</p><ul class="star">
-<li> Forward to <a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li>
-</ul>
+				    <ul>
+	<li>Forward to <a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li>
+</ul>
+
+
+<p>OSWorkflow is fairly different from most other workflow systems available, both commercially and in the open source world. What makes OSWorkflow different is that it is extremely flexible. This can be hard to grasp at first, however. For example, OSWorkflow does not mandate a graphical tool for developing workflows, and the recommended approach is to write the xml workflow descriptors 'by hand'. It is up to the application developer to provide this sort of integration, as well as any integration with existing code and databases. These may seem like problems to someone who is looking for a quick "plug-and-play" workflow solution, but we've found that such a solution never provides enough flexibility to properly fulfill all requirements in a full-blown application. </p>
+
+<p><b>OSWorkflow gives you this flexibility</b>.</p>
+
+<p>OSWorkflow can be considered a "low level" workflow implementation. Situations like "loops" and "conditions" that might be represented by a graphical icon in other workflow systems must be "coded" in OSWorkflow. That's not to say that actual code is needed to implement situations like this, but a scripting language must be employed to specify these conditions. It is not expected that a non-technical user modify workflow. We've found that although some systems provide GUIs that allow for simple editing of workflows, the applications surrounding the workflow usually end up damaged when changes like these are made. We believe it is best for these changes to be made by a developer who is aware of each change. Having said that, the latest version provides a GUI designer that can help with the editing of the workflow.</p>
+
+<p>OSWorkflow is based heavily on the concept of the <em>finite state machine</em>. Each state in represented by the combination of a step ID and a status. A <b>transition</b> from one state to another cannot happen without an action occuring first. There are always at least one or more active states during the lifetime of a workflow. These simple concepts are what lie at the core of the OSWorkflow engine and allow a simple XML file to be translated in to business workflow processes.</p>
+
+<ul>
+	<li>Forward to <a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li>
+</ul>
+
 
                     			    </td>
 		    </tr>

docs/1.2 Requirements.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <ul class="star">
-<li> Back to <a href="1.1 Introduction.html" title="1.1 Introduction">1.1 Introduction</a></li>
-<li> Forward to <a href="1.3 Running the Example App.html" title="1.3 Running the Example App">1.3 Running the Example App</a></li>
-</ul><br/>
-Almost all of the required libraries for OSWorkflow are included in the distribution:<br/>
-
-<ul class="star">
-<li> <a href="http://www.opensymphony.com/oscore" title="Visit page outside Confluence">OSCore 2.0.1+</a></li>
-<li> <a href="http://www.opensymphony.com/propertyset" title="Visit page outside Confluence">PropertySet 1.2+</a></li>
-<li> <a href="http://jakarta.apache.org/commons/logging.html" title="Visit page outside Confluence">Jakarta commons-logging</a></li>
-<li> <a href="http://www.beanshell.org/" title="Visit page outside Confluence">BeanShell</a> (optional)</li>
-<li> <a href="http://oss.software.ibm.com/developerworks/projects/bsf" title="Visit page outside Confluence">BSF</a> (optional)</li>
-<li> EJB interfaces (not neccesarily an EJB container)</li>
-<li> XML parser (Not required for JDK 1.4)</li>
-</ul><br/>
-The core API of OSWorkflow will work with JDK 1.3+. However, the GUI designer application required a 1.4 JVM.<p class="paragraph"><b class="strong">A note about SOAP and job scheduling:</b> GLUE is the SOAP implementation that OSWorkflow uses. We chose to go with GLUE due to the ease of setup as well as the incredible power it offers. GLUE is freely available from <a href="http://www.webmethods.com/solutions/wM_Glue_OEM_ISV/" title="Visit page outside Confluence">WebMethods</a>. If you are going to require SOAP support or <b class="strong">remote</b> Job Scheduling support, you must download the <b class="strong">GLUE Professional</b> libraries. In addition to GLUE, you&#039;ll also need <a href="http://www.part.net/quartz.html" title="Visit page outside Confluence">Quartz</a> for job scheduling. If you don&#039;t wish to use GLUE and/or Quartz, you can provide alternate implementations very easily by using the OSWorkflow API. *If you are going to run Quartz from within your application server or any place that has OSWorkflow properly configured, you do not need GLUE and must configure the JobScheduler to have the arg &quot;local&quot; set to <em class="emphasis">true</em>.</p>In addition to the above libraries, you will have different required libraries or install bases based on the persistence mechanism (WorkflowStore) you choose to use in your application. You can read more about these requirements in the <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a> section. You may also need other libraries based on any utility functions you decide to use. For example, if you use the <b class="strong">OSUserGroupCondition</b> you will need <a href="http://www.opensymphony.com/osuser" title="Visit page outside Confluence">OSUser</a> installed as well. 
-
+				    <ul>
+	<li>Back to <a href="1.1 Introduction.html" title="1.1 Introduction">1.1 Introduction</a></li>
+	<li>Forward to <a href="1.3 Running the Example App.html" title="1.3 Running the Example App">1.3 Running the Example App</a></li>
+</ul>
+
+
+<p>Almost all of the required libraries for OSWorkflow are included in the distribution:</p>
+
+<ul>
+	<li><a href="http://www.opensymphony.com/oscore" title="Visit page outside Confluence">OSCore 2.0.1+</a></li>
+	<li><a href="http://www.opensymphony.com/propertyset" title="Visit page outside Confluence">PropertySet 1.2+</a></li>
+	<li><a href="http://jakarta.apache.org/commons/logging.html" title="Visit page outside Confluence">Jakarta commons-logging</a></li>
+	<li><a href="http://www.beanshell.org/" title="Visit page outside Confluence">BeanShell</a> (optional)</li>
+	<li><a href="http://oss.software.ibm.com/developerworks/projects/bsf" title="Visit page outside Confluence">BSF</a> (optional)</li>
+	<li>EJB interfaces (not neccesarily an EJB container)</li>
+	<li>XML parser (Not required for JDK 1.4)</li>
+</ul>
+
+
+<p>The core API of OSWorkflow will work with JDK 1.3+. However, the GUI designer application required a 1.4 JVM.</p>
+
+<p><b>A note about SOAP and job scheduling:</b> GLUE is one of the SOAP implementations that OSWorkflow uses. You can also use XFire as of OSWorkflow 2.8. GLUE is freely available from <a href="http://www.webmethods.com/solutions/wM_Glue_OEM_ISV/" title="Visit page outside Confluence">WebMethods</a>. If you are going to require SOAP support or <b>remote</b> Job Scheduling support, you should download the <b>GLUE Professional</b> libraries. <a href="http://xfire.codehaus.org" title="Visit page outside Confluence">XFire</a> is an open source Codehaus project.</p>
+
+<p>In addition to GLUE, you'll also need <a href="http://www.part.net/quartz.html" title="Visit page outside Confluence">Quartz</a> for job scheduling. If you don't wish to use GLUE and/or Quartz, you can provide alternate implementations very easily by using the OSWorkflow API. *If you are going to run Quartz from within your application server or any place that has OSWorkflow properly configured, you do not need GLUE and must configure the JobScheduler to have the arg "local" set to <em>true</em>.</p>
+
+<p>In addition to the above libraries, you will have different required libraries or install bases based on the persistence mechanism (WorkflowStore) you choose to use in your application. You can read more about these requirements in the <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a> section. You may also need other libraries based on any utility functions you decide to use. For example, if you use the <b>OSUserGroupCondition</b> you will need <a href="http://www.opensymphony.com/osuser" title="Visit page outside Confluence">OSUser</a> installed as well. </p>
 
                     			    </td>
 		    </tr>

docs/1.3 Running the Example App.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <ul class="star">
-<li> Back to <a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li>
-<li> Forward to <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li>
-</ul><br/>
-<a name="1.3RunningtheExampleApp-top"></a><br/>
-Note that as of version 2.5, the example war application should deploy on most web containers with no external configuration required. The example app now uses memory persistence, so no datasources need to be configured. The instructions below apply for those wishing to configure a persistent store. In order to explore the example workflow, it is recommended that you first deploy the example war as-is, without any persistence.<p class="paragraph">The guides below therefore are only applicable if you would like to deploy the example application using a persistent datastore. For your first run, it is strongly recommended you not bother with these and instead simply deploy the example war.</p>OSWorkflow comes with a very simple example application to help you get started with understanding the concepts OSWorkflow is based upon. The example application can run on any servlet container. The following guides have been provided courtesy of Ed Yu and Egor Kobylkin. If your application server is <br/>
-not listed, read one of the guides below as a starting point. Installation<br/>
-should be very similar.<br/>
+				    <ul>
+	<li>Back to <a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li>
+	<li>Forward to <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li>
+</ul>
+
+
+<a name="1.3RunningtheExampleApp-top"></a>
+<p>Note that as of version 2.5, the example war application should deploy on most web containers with no external configuration required. The example app now uses memory persistence, so no datasources need to be configured. The instructions below apply for those wishing to configure a persistent store. In order to explore the example workflow, it is recommended that you first deploy the example war as-is, without any persistence. The ear example application however is configured to use EJB persistence, and so a full application server is required.</p>
+
+<p>The guides below therefore are only applicable if you would like to deploy the example application using a persistent datastore. For your first run, it is strongly recommended you not bother with these and instead simply deploy the example war.</p>
+
+<p>OSWorkflow comes with a very simple example application to help you get started with understanding the concepts OSWorkflow is based upon. The example application can run on any servlet container. The following guides have been provided courtesy of Ed Yu and Egor Kobylkin. If your application server is <br/>
+not listed, read one of the guides below as a starting point. Installation<br/>
+should be very similar.</p>
+
+<ul>
+	<li><a href="#orion" title="Visit page outside Confluence">Orion</a></li>
+	<li><a href="#jrun" title="Visit page outside Confluence">JRun</a></li>
+	<li><a href="#tomcat40" title="Visit page outside Confluence">Tomcat 4.0.x</a></li>
+	<li><a href="#tomcat41" title="Visit page outside Confluence">Tomcat 4.1.x</a></li>
+</ul>
+
+
+<a name="1.3RunningtheExampleApp-orion"></a>
+<h2><a name="1.3RunningtheExampleApp-Orion">Orion <a href="#top" title="Visit page outside Confluence">top</a></a></h2>
+
+<p>This is a rough guide on how to deploy osworkflow_example.war on Orion 1.5.4 or later.</p>
+
+<p>Setting up persistence<br/>
+--------------------<br/>
+It is important to properly configure pooled datasource for good performance.</p>
+
+<p>For Orion 1.5.4+, the add the following to file config/data-sources.xml<br/>
+to properly configure pooled datasource required by OSWorkflow:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!-- Postgresql Pooled Datasource -&gt;</span>
+	&lt;data-source
+                    class=<span class="code-quote">"com.evermind.sql.DriverManagerDataSource"</span>
+                    name=<span class="code-quote">"NoPoolPostgresql"</span>
+                    location=<span class="code-quote">"jdbc/NoPoolDefaultDS"</span>
+                    xa-location=<span class="code-quote">"jdbc/xa/NoPoolDefaultXADS"</span>
+                    connection-driver=<span class="code-quote">"org.postgresql.Driver"</span>
+                    username=<span class="code-quote">"name"</span>
+                    password=<span class="code-quote">"pass"</span>
+                    url=<span class="code-quote">"jdbc:postgresql://hostname:port/dbname"</span>
+                    inactivity-timeout=<span class="code-quote">"30"</span>
+        /&gt;
+	&lt;data-source
+                    class=<span class="code-quote">"com.evermind.sql.OrionPooledDataSource"</span>
+                    name=<span class="code-quote">"PooledPostgresql"</span>
+                    location=<span class="code-quote">"jdbc/DefaultDS"</span>
+                    pooled-location=<span class="code-quote">"jdbc/DefaultDS"</span>
+                    xa-location=<span class="code-quote">"jdbc/xa/DefaultXADS"</span>
+                    source-location=<span class="code-quote">"jdbc/NoPoolDefaultDS"</span>
+                    connection-driver=<span class="code-quote">"org.postgresql.Driver"</span>
+                    username=<span class="code-quote">"name"</span>
+                    password=<span class="code-quote">"pass"</span>
+                    url=<span class="code-quote">"jdbc:postgresql://hostname:port/dbname"</span>
+                    inactivity-timeout=<span class="code-quote">"30"</span>
+        /&gt;
 
-<ul class="star">
-<li> <a href="#orion" title="Visit page outside Confluence">Orion</a></li>
-<li> <a href="#jrun" title="Visit page outside Confluence">JRun</a></li>
-<li> <a href="#tomcat40" title="Visit page outside Confluence">Tomcat 4.0.x</a></li>
-<li> <a href="#tomcat41" title="Visit page outside Confluence">Tomcat 4.1.x</a></li>
-</ul><br/>
-<a name="1.3RunningtheExampleApp-orion"></a>
-<h2 class="heading2"><a name="1.3RunningtheExampleApp-Orion%3Cahref%3D%22%23top%22title%3D%22VisitpageoutsideConfluence%22%3Etop%3C%2Fa%3E"> Orion <a href="#top" title="Visit page outside Confluence">top</a></a></h2>
+	<span class="code-tag">&lt;!- Oracle Pooled Datasource -&gt;</span>
+	&lt;data-source
+                    class=<span class="code-quote">"oracle.jdbc.pool.OracleDataSource"</span>
+                    name=<span class="code-quote">"Default"</span>
+                    location=<span class="code-quote">"jdbc/DefaultDS"</span>
+                    xa-location=<span class="code-quote">"jdbc/xa/DefaultXADS"</span>
+                    ejb-location=<span class="code-quote">"jdbc/DefaultDS"</span>
+                    connection-driver=<span class="code-quote">"oracle.jdbc.driver.OracleDriver"</span>
+                    username=<span class="code-quote">"name"</span>
+                    password=<span class="code-quote">"pass"</span>
+                    url=<span class="code-quote">"jdbc:oracle:thin:@hostname:port:SID"</span>
+                    inactivity-timeout=<span class="code-quote">"30"</span>
+        /&gt;</pre>
+</div></div>
+<p>In addition, modify the osworkflow.xml to reflect how to access sequence<br/>
+objects for your database.</p>
+
+<p>To use postgresql as the backend database, execute the file tables_postgres.sql<br/>
+against the database and make sure the following is defined in the file<br/>
+osworkflow.xml:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!- Postgresql sequence access -&gt;</span>
+  &lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                  value=<span class="code-quote">"SELECT nextVal('seq_os_wfentry')"</span>/&gt;
+  &lt;property key=<span class="code-quote">"step.sequence"</span> 
+                  value=<span class="code-quote">"SELECT nextVal('seq_os_currentsteps')"</span>/&gt;</pre>
+</div></div>
+<p>To use oracle as the backend database, execute the file tables_oracle.sql<br/>
+against the database and make sure the following is defined in the<br/>
+osworkflow.xml:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!- Oracle sequence access -&gt;</span>
+        &lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                  value=<span class="code-quote">"SELECT seq_os_wfentry.nextval FROM dual"</span>/&gt;
+        &lt;property key=<span class="code-quote">"step.sequence"</span> 
+                  value=<span class="code-quote">"SELECT seq_os_currentsteps.nextval FROM dual"</span>/&gt;</pre>
+</div></div>
+
+<p>WAR Deployment<br/>
+-------------<br/>
+Make a directory under the server home (e.g. C:\orion\oswf), pleace the file<br/>
+osworkflow_example.war file under it.</p>
+
+<p>Modify file config/application.xml and add the following line in:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;web-module id=<span class="code-quote">"oswf"</span> path=<span class="code-quote">"../oswf/osworkflow_example.war"</span> /&gt;</span></pre>
+</div></div>
+<p>Modify file config/default-web-site.xml and add the following line in:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml">&lt;web-app application=<span class="code-quote">"default"</span> load-on-startup=<span class="code-quote">"true"</span> 
+                 name=<span class="code-quote">"oswf"</span> root=<span class="code-quote">"/oswf"</span> /&gt;</pre>
+</div></div>
+<p>Finally go to <a href="http://localhost/oswf/" title="Visit page outside Confluence">&#104;ttp://localhost/oswf/</a> to access the sample application.</p>
+
+<p>You can also deploy the ear example application, which uses EJB persistence <br/>
+rather than the in-memory persistence that the example war webapp uses.</p>
+
+<a name="1.3RunningtheExampleApp-jrun"></a>
+<h2><a name="1.3RunningtheExampleApp-JRun">JRun <a href="#top" title="Visit page outside Confluence">top</a></a></h2>
+
+<p>This is a rough guide on how to deploy osworkflow_example.war on JRun4.</p>
+
+
+<p>Setting up persistence<br/>
+--------------------<br/>
+It is important to properly configure pooled datasource for good performance.</p>
+
+<p>For JRun4, it is pretty easy to configure pooled datasource when defining JDBC<br/>
+resources using the JMC. Startup the admin server and the default server and<br/>
+then use JMC to define a JDBC datasource for your database within the default<br/>
+server(port 8100). Keep the checkbox clicked for pool connection when adding<br/>
+in the datasource. Make sure to verify the datasource after adding it in.</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-none">JNDI Name		jdbc/DefaultDS
+Driver Class Name	org.postgresql.Driver
+URL			jdbc:postgresql://hostname:port/dbName
+Description		OSWorkflow example Postgresql database. 
+Pool Connections	X
+Pool Statements		X
+Native Results		X
+User Name		user
+Password		pass
+Verify Password	pass	pass
 
-<div class="code"><div class="codeContent">
-<pre>This is a quick stab on how to deploy osworkflow&#95;example.war &#10;on Orion 1.5.4 or later.&#10;&#10;Setting up persistence&#10;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#10;It is important to properly configure pooled datasource <span class="java&#45;keyword">for</span> good performance.&#10;&#10;For Orion 1.5.4&#43;, the add the following to file config/data&#45;sources.xml&#10;to properly configure pooled datasource required by OSWorkflow:&#10;&#10;	&lt;&#33;&#45;&#45; Postgresql Pooled Datasource &#45;&gt;&#10;	&lt;data&#45;source&#10;                    class=<span class="java&#45;quote">&quot;com.evermind.sql.DriverManagerDataSource&quot;</span>&#10;                    name=<span class="java&#45;quote">&quot;NoPoolPostgresql&quot;</span>&#10;                    location=<span class="java&#45;quote">&quot;jdbc/NoPoolDefaultDS&quot;</span>&#10;                    xa&#45;location=<span class="java&#45;quote">&quot;jdbc/xa/NoPoolDefaultXADS&quot;</span>&#10;                    connection&#45;driver=<span class="java&#45;quote">&quot;org.postgresql.Driver&quot;</span>&#10;                    username=<span class="java&#45;quote">&quot;name&quot;</span>&#10;                    password=<span class="java&#45;quote">&quot;pass&quot;</span>&#10;                    url=<span class="java&#45;quote">&quot;jdbc:postgresql:<span class="java&#45;comment">//hostname:port/dbname&quot;</span></span>&#10;                    inactivity&#45;timeout=<span class="java&#45;quote">&quot;30&quot;</span>&#10;        /&gt;&#10;	&lt;data&#45;source&#10;                    class=<span class="java&#45;quote">&quot;com.evermind.sql.OrionPooledDataSource&quot;</span>&#10;                    name=<span class="java&#45;quote">&quot;PooledPostgresql&quot;</span>&#10;                    location=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>&#10;                    pooled&#45;location=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>&#10;                    xa&#45;location=<span class="java&#45;quote">&quot;jdbc/xa/DefaultXADS&quot;</span>&#10;                    source&#45;location=<span class="java&#45;quote">&quot;jdbc/NoPoolDefaultDS&quot;</span>&#10;                    connection&#45;driver=<span class="java&#45;quote">&quot;org.postgresql.Driver&quot;</span>&#10;                    username=<span class="java&#45;quote">&quot;name&quot;</span>&#10;                    password=<span class="java&#45;quote">&quot;pass&quot;</span>&#10;                    url=<span class="java&#45;quote">&quot;jdbc:postgresql:<span class="java&#45;comment">//hostname:port/dbname&quot;</span></span>&#10;                    inactivity&#45;timeout=<span class="java&#45;quote">&quot;30&quot;</span>&#10;        /&gt;&#10;&#10;	&lt;&#33;&#45; Oracle Pooled Datasource &#45;&gt;&#10;	&lt;data&#45;source&#10;                    class=<span class="java&#45;quote">&quot;oracle.jdbc.pool.OracleDataSource&quot;</span>&#10;                    name=<span class="java&#45;quote">&quot;Default&quot;</span>&#10;                    location=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>&#10;                    xa&#45;location=<span class="java&#45;quote">&quot;jdbc/xa/DefaultXADS&quot;</span>&#10;                    ejb&#45;location=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>&#10;                    connection&#45;driver=<span class="java&#45;quote">&quot;oracle.jdbc.driver.OracleDriver&quot;</span>&#10;                    username=<span class="java&#45;quote">&quot;name&quot;</span>&#10;                    password=<span class="java&#45;quote">&quot;pass&quot;</span>&#10;                    url=<span class="java&#45;quote">&quot;jdbc:oracle:thin:&#64;hostname:port:SID&quot;</span>&#10;                    inactivity&#45;timeout=<span class="java&#45;quote">&quot;30&quot;</span>&#10;        /&gt;&#10;&#10;&#10;In addition, modify the osworkflow.xml to reflect how to access sequence&#10;objects <span class="java&#45;keyword">for</span> your database.&#10;&#10;To use postgresql as the backend database, execute the file tables&#95;postgres.sql&#10;against the database and make sure the following is defined in the file&#10;osworkflow.xml:&#10;&#10;  &lt;&#33;&#45; Postgresql sequence access &#45;&gt;&#10;  &lt;property key=<span class="java&#45;quote">&quot;entry.sequence&quot;</span> &#10;                  value=<span class="java&#45;quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;wfentry&#039;)&quot;</span>/&gt;&#10;  &lt;property key=<span class="java&#45;quote">&quot;step.sequence&quot;</span> &#10;                  value=<span class="java&#45;quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;currentsteps&#039;)&quot;</span>/&gt;&#10;&#10;To use oracle as the backend database, execute the file tables&#95;oracle.sql&#10;against the database and make sure the following is defined in the&#10;osworkflow.xml:&#10;&#10;        &lt;&#33;&#45; Oracle sequence access &#45;&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;entry.sequence&quot;</span> &#10;                  value=<span class="java&#45;quote">&quot;SELECT seq&#95;os&#95;wfentry.nextval FROM dual&quot;</span>/&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;step.sequence&quot;</span> &#10;                  value=<span class="java&#45;quote">&quot;SELECT seq&#95;os&#95;currentsteps.nextval FROM dual&quot;</span>/&gt;&#10;&#10;&#10;WAR Deployment&#10;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#10;Make a directory under the server home (e.g. C:&#92;orion&#92;oswf), pleace the file&#10;osworkflow&#95;example.war file under it.&#10;&#10;Modify file config/application.xml and add the following line in:&#10;&#10;	&lt;web&#45;module id=<span class="java&#45;quote">&quot;oswf&quot;</span> path=<span class="java&#45;quote">&quot;../oswf/osworkflow&#95;example.war&quot;</span> /&gt;&#10;&#10;Modify file config/<span class="java&#45;keyword">default</span>&#45;web&#45;site.xml and add the following line in:&#10;&#10;	&lt;web&#45;app application=<span class="java&#45;quote">&quot;<span class="java&#45;keyword">default</span>&quot;</span> load&#45;on&#45;startup=<span class="java&#45;quote">&quot;<span class="java&#45;keyword">true</span>&quot;</span> &#10;                 name=<span class="java&#45;quote">&quot;oswf&quot;</span> root=<span class="java&#45;quote">&quot;/oswf&quot;</span> /&gt;&#10;&#10;Finally go to http:<span class="java&#45;comment">//localhost/oswf to access the sample application.</span>&#10;&#10;You can also deploy the ear example application, which uses EJB persistence &#10;rather than the in&#45;memory persistence that the example war webapp uses.</pre>
-</div></div><p class="paragraph"><a name="1.3RunningtheExampleApp-jrun"></a>
-<h2 class="heading2"><a name="1.3RunningtheExampleApp-JRun%3Cahref%3D%22%23top%22title%3D%22VisitpageoutsideConfluence%22%3Etop%3C%2Fa%3E"> JRun <a href="#top" title="Visit page outside Confluence">top</a></a></h2></p><div class="code"><div class="codeContent">
-<pre>This is a quick stab on how to deploy osworkflow&#95;example.war on JRun4.&#10;&#10;&#10;Setting up persistence&#10;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#10;It is important to properly configure pooled datasource <span class="java&#45;keyword">for</span> good performance.&#10;&#10;For JRun4, it is pretty easy to configure pooled datasource when defining JDBC&#10;resources using the JMC. Startup the admin server and the <span class="java&#45;keyword">default</span> server and&#10;then use JMC to define a JDBC datasource <span class="java&#45;keyword">for</span> your database within the <span class="java&#45;keyword">default</span>&#10;server(port 8100). Keep the checkbox clicked <span class="java&#45;keyword">for</span> pool connection when adding&#10;in the datasource. Make sure to verify the datasource after adding it in.&#10;&#10;JNDI Name		jdbc/DefaultDS&#10;Driver <span class="java&#45;object">Class</span> Name	org.postgresql.Driver&#10;URL			jdbc:postgresql:<span class="java&#45;comment">//hostname:port/dbName</span>&#10;Description		OSWorkflow example Postgresql database. &#10;Pool Connections	X&#10;Pool Statements		X&#10;Native Results		X&#10;User Name		user&#10;Password		pass&#10;Verify Password	pass	pass&#10;&#10;JNDI Name		jdbc/DefaultDS&#10;Driver <span class="java&#45;object">Class</span> Name	oracle.jdbc.pool.OracleDataSource&#10;URL			jdbc:oracle:thin:&#64;hostname:port:SID&#10;Description		OSWorkflow example Oracle database. &#10;Pool Connections	X&#10;Pool Statements		X&#10;Native Results		X&#10;User Name		user&#10;Password		pass&#10;Verify Password	pass	pass&#10;&#10;In addition, modify the osworkflow.xml to reflect how to access sequence&#10;objects <span class="java&#45;keyword">for</span> your database.&#10;&#10;To use postgresql as the backend database, execute the file tables&#95;postgres.sql&#10;against the database and make sure the following is defined in the file&#10;osworkflow.xml:&#10;&#10;        &lt;&#33;&#45;&#45; Postgresql sequence access &#45;&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;entry.sequence&quot;</span> &#10;                        value=<span class="java&#45;quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;wfentry&#039;)&quot;</span>/&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;step.sequence&quot;</span> &#10;                        value=<span class="java&#45;quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;currentsteps&#039;)&quot;</span>/&gt;&#10;&#10;To use oracle as the backend database, execute the file tables&#95;oracle.sql&#10;against the database and make sure the following is defined in the&#10;osworkflow.xml:&#10;&#10;        &lt;&#33;&#45; Oracle sequence access &#45;&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;entry.sequence&quot;</span> &#10;                  value=<span class="java&#45;quote">&quot;SELECT seq&#95;os&#95;wfentry.nextval FROM dual&quot;</span>/&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;step.sequence&quot;</span> &#10;                  value=<span class="java&#45;quote">&quot;SELECT seq&#95;os&#95;currentsteps.nextval FROM dual&quot;</span>/&gt;&#10;&#10;&#10;WAR Deployment&#10;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#10;To deploy osworkflow&#95;example.war, place the file under the directory&#10;servers/<span class="java&#45;keyword">default</span> after setting up the persistence mechanism outlined above.&#10;Restart the <span class="java&#45;keyword">default</span> server (port 8100).&#10;&#10;Finally, go to http:<span class="java&#45;comment">//localhost:8100/osworkflow&#95;example to </span>&#10;access the sample application.</pre>
-</div></div><p class="paragraph"><h2 class="heading2"><a name="1.3RunningtheExampleApp-Tomcat4.0.x%3Caname%3D%221.3RunningtheExampleApptomcat40%22%3E%3C%2Fa%3E%3Cahref%3D%22%23top%22title%3D%22VisitpageoutsideConfluence%22%3Etop%3C%2Fa%3E"> Tomcat 4.0.x <a name="1.3RunningtheExampleApp-tomcat40"></a>&#160;<a href="#top" title="Visit page outside Confluence">top</a></a></h2></p><ul class="star">
-<li> <a href="#tomcat41" title="Visit page outside Confluence">Tomcat 4.1.x</a></li>
-</ul>
-<div class="code"><div class="codeContent">
-<pre>README&#45;Tomcat.txt&#10;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#10;This is a quick stab on how to deploy osworkflow&#95;example.war on Tomcat 4.0.X.&#10;&#10;&#10;Setting up persistence&#10;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#10;It is important to properly configure pooled datasource <span class="java&#45;keyword">for</span> good performance.&#10;&#10;Unfortunately, there is no good documentation on how to setup Tyrex in Tomcat&#10;4.0 and compounded by the fact that Tyrex will be deprecated begining in Tomcat&#10;version 4.1, there is no good way to improve performance under Tomcat 4.0.&#10;Nonetheless, there are documentation on how to configure Oracle pooled&#10;datasource factory in Tomcat 4.0.X. Refer to the urls&#10;http:<span class="java&#45;comment">//www.apachelabs.org/tomcat&#45;user/20020&#91;OS:3&#45;7&#93;.mbox/threads.html,</span>&#10;<span class="java&#45;keyword">try</span> it out and let me know <span class="java&#45;keyword">if</span> you are successful. I&#039;ve also attempted to&#10;use the LE version of Tomcat 4.0.4 (jakarta&#45;tomcat&#45;4.0.4&#45;LE&#45;jdk14.&#42;) without&#10;any luck (NPE), whereas the full version works fine <span class="java&#45;keyword">for</span> me.&#10;&#10;Please read the WAR Deployment section below and then come back here.&#10;&#10;It is important to copy the osworkflow&#95;example.war into TOMCAT&#95;HOME/webapps&#10;and startup and shutdown the server before making the modifications to&#10;TOMCAT&#95;HOME/conf/server.xml to include:&#10;&#10;        &lt;&#33;&#45;&#45; OSWorkflow Example Context &#45;&gt;&#10;        &lt;Context path=<span class="java&#45;quote">&quot;/osworkflow&#95;example&quot;</span> &#10;                 docBase=<span class="java&#45;quote">&quot;osworkflow&#95;example&quot;</span> debug=<span class="java&#45;quote">&quot;0&quot;</span>&#10;                 reloadable=<span class="java&#45;quote">&quot;<span class="java&#45;keyword">true</span>&quot;</span> crossContext=<span class="java&#45;quote">&quot;<span class="java&#45;keyword">true</span>&quot;</span>&gt;&#10;	  &lt;Resource name=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span> auth=<span class="java&#45;quote">&quot;Container&quot;</span>&#10;            type=<span class="java&#45;quote">&quot;javax.sql.DataSource&quot;</span>/&gt;&#10;	  &lt;ResourceParams name=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>&gt;&#10;            &lt;parameter&gt;&lt;name&gt;user&lt;/name&gt;&lt;value&gt;user&lt;/value&gt;&lt;/parameter&gt;&#10;            &lt;parameter&gt;&lt;name&gt;password&lt;/name&gt;&lt;value&gt;pass&lt;/value&gt;&lt;/parameter&gt;&#10;	    &lt;parameter&gt;&#10;	      &lt;name&gt;driverClassName&lt;/name&gt;&#10;	      &lt;&#33;&#45; Oracle &#45;&gt;&#10;              &lt;value&gt;oracle.jdbc.driver.OracleDriver&lt;/value&gt;&#10;&#10;	      &lt;&#33;&#45; Postgresql&#10;	      &lt;value&gt;org.postgresql.Driver&lt;/value&gt;&#10;	      &#45;&gt;&#10;	    &lt;/parameter&gt;&#10;	    &lt;parameter&gt;&#10;	      &lt;name&gt;driverName&lt;/name&gt;&#10;	      &lt;&#33;&#45; Oracle &#45;&gt;&#10;	      &lt;value&gt;jdbc:oracle:thin:&#64;hostname:port:SID&lt;/value&gt;&#10;&#10;	      &lt;&#33;&#45; Postgresql&#10;	      &lt;value&gt;jdbc:postgresql:<span class="java&#45;comment">//hostname:port/dbName&lt;/value&gt;</span>&#10;	      &#45;&gt;&#10;	    &lt;/parameter&gt;&#10;	  &lt;/ResourceParams&gt;&#10;	&lt;/Context&gt;&#10;      &lt;/Host&gt;&#10;    &lt;/Engine&gt;&#10;  &lt;/Service&gt;&#10;&#10;Make sure your JDBC driver is in TOMCAT&#95;HOME/common/lib. For oracle, you may&#10;need to rename classes12.zip into classes12.jar <span class="java&#45;keyword">for</span> it to work.&#10;&#10;In addition, modify the osworkflow.xml to reflect how to access sequence&#10;objects <span class="java&#45;keyword">for</span> your database.&#10;&#10;To use postgresql as the backend database, execute the file tables&#95;postgres.sql&#10;against the database and make sure the following is defined in the file&#10;osworkflow.xml:&#10;&#10;        &lt;&#33;&#45; Postgresql sequence access &#45;&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;entry.sequence&quot;</span> &#10;                        value=<span class="java&#45;quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;wfentry&#039;)&quot;</span>/&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;step.sequence&quot;</span> &#10;                        value=<span class="java&#45;quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;currentsteps&#039;)&quot;</span>/&gt;&#10;&#10;To use oracle as the backend database, execute the file tables&#95;oracle.sql&#10;against the database and make sure the following is defined in the&#10;osworkflow.xml:&#10;&#10;        &lt;&#33;&#45; Oracle sequence access &#45;&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;entry.sequence&quot;</span> &#10;                  value=<span class="java&#45;quote">&quot;SELECT seq&#95;os&#95;wfentry.nextval FROM dual&quot;</span>/&gt;&#10;        &lt;property key=<span class="java&#45;quote">&quot;step.sequence&quot;</span> &#10;                  value=<span class="java&#45;quote">&quot;SELECT seq&#95;os&#95;currentsteps.nextval FROM dual&quot;</span>/&gt;&#10;&#10;&#10;WAR Deployment&#10;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#10;To deploy osworkflow&#95;example.war, place it under the directory&#10;TOMCAT&#95;HOME/webapps, startup and shutdown the server. Then set up the&#10;persistence mechanism as outlined above. Next, modify the server.xml file to&#10;configure the data source as outlined above.&#10;&#10;Finally, restart the server. Then, go to &#10;http:<span class="java&#45;comment">//localhost:8080/osworkflow&#95;example to access the sample application.</span></pre>
-</div></div><p class="paragraph"><h2 class="heading2"><a name="1.3RunningtheExampleApp-Tomcat4.1.x%3Caname%3D%221.3RunningtheExampleApptomcat41%22%3E%3C%2Fa%3E%3Cahref%3D%22%23top%22title%3D%22VisitpageoutsideConfluence%22%3Etop%3C%2Fa%3E"> Tomcat 4.1.x <a name="1.3RunningtheExampleApp-tomcat41"></a>  <a href="#top" title="Visit page outside Confluence">top</a></a></h2></p>&lt;Egor Kobylkin egor.kobylkin@o2.com&gt;<br/>
-This is a quick stab on how to deploy osworkflow_example.war on Tomcat 4.1.x. (tested on 4.1.27)<p class="paragraph">To deploy osworkflow_example.war, place it under the directory<br/>
-TOMCAT_HOME/webapps, startup and shutdown the server. (Ignore if you have already done it)</p><em class="emphasis">Note that to run the demonstration there is no necessity to create a persistent store - the demonstration will run without it provided that the Tomcat server is not shut down</em><p class="paragraph"><b class="strong">Setting up persistence</b></p>Put jboss-j2ee.jar into TOMCAT_HOME/common/endorsed (get it from JBoss.org) to enable EJB lookup. <p class="paragraph">Next you have to make modifications to<br/>
-TOMCAT_HOME/conf/server.xml to include:
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;&#33;&#45;&#45; OSWorkflow JNDI JDBC Data Source Example. egor.kobylkin&#64;o2.com &#45;&gt;</span>&#10;&#10;<span class="xml-tag">&lt;Context path=<span class="xml-quote">&quot;/osworkflow&#95;example&quot;</span> docBase=<span class="xml-quote">&quot;osworkflow&#45;2.7.0&#45;example&quot;</span> &#10;         debug= <span class="xml-quote">&quot;99&quot;</span> reloadable=<span class="xml-quote">&quot;true&quot;</span> crossContext=<span class="xml-quote">&quot;true&quot;</span> &#10;&#10;verbosity=<span class="xml-quote">&quot;DEBUG&quot;</span>&gt;</span>&#10;<span class="xml-tag">&lt;&#33;&#45; debug level is set to paranoid, to know what is happening, &#10;     turn it off once you do not need it &#45;&gt;</span>&#10;&#10;<span class="xml-tag">&lt;Logger className=<span class="xml-quote">&quot;org.apache.catalina.logger.FileLogger&quot;</span>&#10;        prefix=<span class="xml-quote">&quot;OSWorkflow.&quot;</span> suffix=<span class="xml-quote">&quot;.log&quot;</span> timestamp=<span class="xml-quote">&quot;true&quot;</span>/&gt;</span>&#10;<span class="xml-tag">&lt;&#33;&#45; &#10;    put log4j.jar into:&#10;    TOMCAT&#95;ROOT/webapp/osworkflow&#45;2.7.0&#45;example/WEB&#45;INF/lib &#10;    if you want to use it for logging &#10;&#45;&gt;</span>&#10;&#10;<span class="xml-tag">&lt;Resource name=<span class="xml-quote">&quot;jdbc/DefaultDS&quot;</span> auth=<span class="xml-quote">&quot;Container&quot;</span> &#10;                 type=<span class="xml-quote">&quot;javax.sql.DataSource&quot;</span>/&gt;</span>&#10;<span class="xml-tag">&lt;&#33;&#45; name=<span class="xml-quote">&quot;jdbc/DefaultDS&quot;</span> is used in other components of the &#10;     Example App, do not change it here&#33; &#45;&gt;</span>&#10;&#10;<span class="xml-tag">&lt;ResourceParams name=<span class="xml-quote">&quot;jdbc/DefaultDS&quot;</span>&gt;</span>&#10;  <span class="xml-tag">&lt;parameter&gt;</span>&#10;    <span class="xml-tag">&lt;name&gt;</span>factory<span class="xml-tag">&lt;/name&gt;</span>&#10;    <span class="xml-tag">&lt;value&gt;</span>org.apache.commons.dbcp.BasicDataSourceFactory<span class="xml-tag">&lt;/value&gt;</span>&#10;  <span class="xml-tag">&lt;/parameter&gt;</span>&#10;  <span class="xml-tag">&lt;parameter&gt;</span>&#10;    <span class="xml-tag">&lt;name&gt;</span>driverClassName<span class="xml-tag">&lt;/name&gt;</span>&#10;    <span class="xml-tag">&lt;value&gt;</span>oracle.jdbc.driver.OracleDriver<span class="xml-tag">&lt;/value&gt;</span>&#10;  <span class="xml-tag">&lt;/parameter&gt;</span>&#10;  <span class="xml-tag">&lt;parameter&gt;</span>&#10;    <span class="xml-tag">&lt;name&gt;</span>url<span class="xml-tag">&lt;/name&gt;</span>&#10;    <span class="xml-tag">&lt;value&gt;</span>jdbc:oracle:thin:&#64;yourserver.com:port:SID<span class="xml-tag">&lt;/value&gt;</span>&#10;  <span class="xml-tag">&lt;/parameter&gt;</span>&#10;  <span class="xml-tag">&lt;parameter&gt;</span>&#10;    <span class="xml-tag">&lt;name&gt;</span>username<span class="xml-tag">&lt;/name&gt;</span>&#10;    <span class="xml-tag">&lt;value&gt;</span>your&#95;database&#95;user&#95;name&#95;here<span class="xml-tag">&lt;/value&gt;</span>&#10;  <span class="xml-tag">&lt;/parameter&gt;</span>&#10;  <span class="xml-tag">&lt;parameter&gt;</span>&#10;    <span class="xml-tag">&lt;name&gt;</span>password<span class="xml-tag">&lt;/name&gt;</span>&#10;    <span class="xml-tag">&lt;value&gt;</span>your&#95;password&#95;here<span class="xml-tag">&lt;/value&gt;</span>&#10;  <span class="xml-tag">&lt;/parameter&gt;</span>&#10;  <span class="xml-tag">&lt;parameter&gt;</span>&#10;    <span class="xml-tag">&lt;name&gt;</span>maxActive<span class="xml-tag">&lt;/name&gt;</span>&#10;    <span class="xml-tag">&lt;value&gt;</span>20<span class="xml-tag">&lt;/value&gt;</span>&#10;  <span class="xml-tag">&lt;/parameter&gt;</span>&#10;  <span class="xml-tag">&lt;parameter&gt;</span>&#10;    <span class="xml-tag">&lt;name&gt;</span>maxIdle<span class="xml-tag">&lt;/name&gt;</span>&#10;    <span class="xml-tag">&lt;value&gt;</span>10<span class="xml-tag">&lt;/value&gt;</span>&#10;  <span class="xml-tag">&lt;/parameter&gt;</span>&#10;  <span class="xml-tag">&lt;parameter&gt;</span>&#10;    <span class="xml-tag">&lt;name&gt;</span>maxWait<span class="xml-tag">&lt;/name&gt;</span>&#10;    <span class="xml-tag">&lt;value&gt;</span>&#45;1<span class="xml-tag">&lt;/value&gt;</span>&#10;  <span class="xml-tag">&lt;/parameter&gt;</span>&#10;<span class="xml-tag">&lt;/ResourceParams&gt;</span>&#10;<span class="xml-tag">&lt;/Context&gt;</span>&#10;&#10;<span class="xml-tag">&lt;&#33;&#45; OSWorkflow JNDI Data Source &#45;&gt;</span></pre>
-</div></div></p>Some documentation on how to configure JNDI / JDBC data sources: <br/>
+JNDI Name		jdbc/DefaultDS
+Driver Class Name	oracle.jdbc.pool.OracleDataSource
+URL			jdbc:oracle:thin:@hostname:port:SID
+Description		OSWorkflow example Oracle database. 
+Pool Connections	X
+Pool Statements		X
+Native Results		X
+User Name		user
+Password		pass
+Verify Password	pass	pass</pre>
+</div></div>
+<p>In addition, modify the osworkflow.xml to reflect how to access sequence<br/>
+objects for your database.</p>
+
+<p>To use postgresql as the backend database, execute the file tables_postgres.sql<br/>
+against the database and make sure the following is defined in the file<br/>
+osworkflow.xml:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!-- Postgresql sequence access -&gt;</span>
+        &lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                        value=<span class="code-quote">"SELECT nextVal('seq_os_wfentry')"</span>/&gt;
+        &lt;property key=<span class="code-quote">"step.sequence"</span> 
+                        value=<span class="code-quote">"SELECT nextVal('seq_os_currentsteps')"</span>/&gt;</pre>
+</div></div>
+<p>To use oracle as the backend database, execute the file tables_oracle.sql<br/>
+against the database and make sure the following is defined in the<br/>
+osworkflow.xml:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!- Oracle sequence access -&gt;</span>
+        &lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                  value=<span class="code-quote">"SELECT seq_os_wfentry.nextval FROM dual"</span>/&gt;
+        &lt;property key=<span class="code-quote">"step.sequence"</span> 
+                  value=<span class="code-quote">"SELECT seq_os_currentsteps.nextval FROM dual"</span>/&gt;</pre>
+</div></div>
+
+<p>WAR Deployment<br/>
+-------------<br/>
+To deploy osworkflow_example.war, place the file under the directory<br/>
+servers/default after setting up the persistence mechanism outlined above.<br/>
+Restart the default server (port 8100).</p>
+
+<p>Finally, go to <a href="http://localhost:8100/osworkflow_example" title="Visit page outside Confluence">&#104;ttp://localhost:8100/osworkflow_example</a> to <br/>
+access the sample application.</p>
+
+<h2><a name="1.3RunningtheExampleApp-Tomcat4.0.x">Tomcat 4.0.x <a name="1.3RunningtheExampleApp-tomcat40"></a> <a href="#top" title="Visit page outside Confluence">top</a></a></h2>
+
+<ul>
+	<li><a href="#tomcat41" title="Visit page outside Confluence">Tomcat 4.1.x</a></li>
+</ul>
+
+
+<p>README-Tomcat.txt<br/>
+----------------------------------------------<br/>
+This is a quick stab on how to deploy osworkflow_example.war on Tomcat 4.0.X.</p>
+
+
+<p>Setting up persistence<br/>
+--------------------<br/>
+It is important to properly configure pooled datasource for good performance.</p>
+
+<p>Unfortunately, there is no good documentation on how to setup Tyrex in Tomcat<br/>
+4.0 and compounded by the fact that Tyrex will be deprecated begining in Tomcat<br/>
+version 4.1, there is no good way to improve performance under Tomcat 4.0.<br/>
+Nonetheless, there are documentation on how to configure Oracle pooled<br/>
+datasource factory in Tomcat 4.0.X. Refer to the urls<br/>
+<a href="http://www.apachelabs.org/tomcat-user/20020OS:3-7.mbox/threads.html" title="Visit page outside Confluence">&#104;ttp://www.apachelabs.org/tomcat-user/20020OS:3-7.mbox/threads.html</a>,<br/>
+try it out and let me know if you are successful. I've also attempted to<br/>
+use the LE version of Tomcat 4.0.4 (jakarta-tomcat-4.0.4-LE-jdk14.*) without<br/>
+any luck (NPE), whereas the full version works fine for me.</p>
+
+<p>Please read the WAR Deployment section below and then come back here.</p>
+
+<p>It is important to copy the osworkflow_example.war into TOMCAT_HOME/webapps<br/>
+and startup and shutdown the server before making the modifications to<br/>
+TOMCAT_HOME/conf/server.xml to include:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!-- OSWorkflow Example Context -&gt;</span>
+        &lt;Context path=<span class="code-quote">"/osworkflow_example"</span> 
+                 docBase=<span class="code-quote">"osworkflow_example"</span> debug=<span class="code-quote">"0"</span>
+                 reloadable=<span class="code-quote">"true"</span> crossContext=<span class="code-quote">"true"</span>&gt;
+	  &lt;Resource name=<span class="code-quote">"jdbc/DefaultDS"</span> auth=<span class="code-quote">"Container"</span>
+            type=<span class="code-quote">"javax.sql.DataSource"</span>/&gt;
+	  <span class="code-tag">&lt;ResourceParams name=<span class="code-quote">"jdbc/DefaultDS"</span>&gt;</span>
+            <span class="code-tag">&lt;parameter&gt;</span><span class="code-tag">&lt;name&gt;</span>user<span class="code-tag">&lt;/name&gt;</span><span class="code-tag">&lt;value&gt;</span>user<span class="code-tag">&lt;/value&gt;</span><span class="code-tag">&lt;/parameter&gt;</span>
+            <span class="code-tag">&lt;parameter&gt;</span><span class="code-tag">&lt;name&gt;</span>password<span class="code-tag">&lt;/name&gt;</span><span class="code-tag">&lt;value&gt;</span>pass<span class="code-tag">&lt;/value&gt;</span><span class="code-tag">&lt;/parameter&gt;</span>
+	    <span class="code-tag">&lt;parameter&gt;</span>
+	      <span class="code-tag">&lt;name&gt;</span>driverClassName<span class="code-tag">&lt;/name&gt;</span>
+	      <span class="code-tag">&lt;!- Oracle -&gt;</span>
+              <span class="code-tag">&lt;value&gt;</span>oracle.jdbc.driver.OracleDriver<span class="code-tag">&lt;/value&gt;</span>
 
-<ul class="star">
-<li> <a href="http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-datasource-examples-howto.html" title="Visit page outside Confluence">&#104;ttp://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-datasource-examples-howto.html</a></li>
-</ul>
-<ul class="star">
-<li> <a href="http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-resources-howto.html" title="Visit page outside Confluence">&#104;ttp://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-resources-howto.html</a></li>
-</ul><br/>
-Make sure your JDBC driver is in TOMCAT_HOME/common/lib. For oracle, you may<br/>
-need to rename classes12.zip into classes12.jar for it to work. <br/>
-For Oracle9 DB use only the JDBC thin driver of version 9 or higher. <p class="paragraph">In addition, modify the osworkflow.xml to reflect how to access sequence<br/>
-objects for your database. <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a>&#160;<br/>
-A Description of the entries in osworkflow.xml can be found <a href="http://www.opensymphony.com/osworkflow/api/com/opensymphony/workflow/spi/jdbc/JDBCWorkflowStore.html" title="Visit page outside Confluence">here</a></p>To use postgresql as the backend database, execute the file tables_postgres.sql<br/>
-against the database and make sure the following is defined in the file<br/>
-osworkflow.xml:<br/>
+	      &lt;!- Postgresql
+	      <span class="code-tag">&lt;value&gt;</span>org.postgresql.Driver<span class="code-tag">&lt;/value&gt;</span>
+	      -&gt;
+	    <span class="code-tag">&lt;/parameter&gt;</span>
+	    <span class="code-tag">&lt;parameter&gt;</span>
+	      <span class="code-tag">&lt;name&gt;</span>driverName<span class="code-tag">&lt;/name&gt;</span>
+	      <span class="code-tag">&lt;!- Oracle -&gt;</span>
+	      <span class="code-tag">&lt;value&gt;</span>jdbc:oracle:thin:@hostname:port:SID<span class="code-tag">&lt;/value&gt;</span>
 
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;&#33;&#45; Postgresql sequence access &#45;&gt;</span>&#10;        <span class="xml-tag">&lt;property key=<span class="xml-quote">&quot;entry.sequence&quot;</span> &#10;                        value=<span class="xml-quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;wfentry&#039;)&quot;</span>/&gt;</span>&#10;        <span class="xml-tag">&lt;property key=<span class="xml-quote">&quot;step.sequence&quot;</span> &#10;                       value=<span class="xml-quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;currentsteps&#039;)&quot;</span>/&gt;</span></pre>
-</div></div><p class="paragraph">To use oracle as the backend database, execute the file tables_oracle.sql<br/>
-against the database (watch out for the missing comma in the file) and make  sure the following is defined in the osworkflow.xml file:</p><div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;&#33;&#45; Oracle sequence access &#45;&#45;&gt;</span>&#10;        <span class="xml-tag">&lt;property key=<span class="xml-quote">&quot;entry.sequence&quot;</span> &#10;                  value=<span class="xml-quote">&quot;SELECT seq&#95;os&#95;wfentry.nextval FROM dual&quot;</span>/&gt;</span>&#10;        <span class="xml-tag">&lt;property key=<span class="xml-quote">&quot;step.sequence&quot;</span> &#10;                  value=<span class="xml-quote">&quot;SELECT seq&#95;os&#95;currentsteps.nextval FROM dual&quot;</span>/&gt;</span></pre>
-</div></div><p class="paragraph">Finally, restart the server. Then, go to:<br/>
-<a href="http://localhost:your_port/osworkflow-2.7.0-example" title="Visit page outside Confluence">&#104;ttp://localhost:your_port/osworkflow-2.7.0-example</a>&#160;<br/>
-(or whatever you&#039;ve mapped the webapp to in your web container) to access <br/>
-the sample application.</p><ul class="star">
-<li> Back to <a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li>
-<li> Forward to <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li>
-</ul>
+	      &lt;!- Postgresql
+	      <span class="code-tag">&lt;value&gt;</span>jdbc:postgresql://hostname:port/dbName<span class="code-tag">&lt;/value&gt;</span>
+	      -&gt;
+	    <span class="code-tag">&lt;/parameter&gt;</span>
+	  <span class="code-tag">&lt;/ResourceParams&gt;</span>
+	<span class="code-tag">&lt;/Context&gt;</span>
+      <span class="code-tag">&lt;/Host&gt;</span>
+    <span class="code-tag">&lt;/Engine&gt;</span>
+  <span class="code-tag">&lt;/Service&gt;</span></pre>
+</div></div>
+<p>Make sure your JDBC driver is in TOMCAT_HOME/common/lib. For oracle, you may<br/>
+need to rename classes12.zip into classes12.jar for it to work.</p>
+
+<p>In addition, modify the osworkflow.xml to reflect how to access sequence<br/>
+objects for your database.</p>
+
+<p>To use postgresql as the backend database, execute the file tables_postgres.sql<br/>
+against the database and make sure the following is defined in the file<br/>
+osworkflow.xml:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!- Postgresql sequence access -&gt;</span>
+        &lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                        value=<span class="code-quote">"SELECT nextVal('seq_os_wfentry')"</span>/&gt;
+        &lt;property key=<span class="code-quote">"step.sequence"</span> 
+                        value=<span class="code-quote">"SELECT nextVal('seq_os_currentsteps')"</span>/&gt;</pre>
+</div></div>
+<p>To use oracle as the backend database, execute the file tables_oracle.sql<br/>
+against the database and make sure the following is defined in the<br/>
+osworkflow.xml:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!- Oracle sequence access -&gt;</span>
+        &lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                  value=<span class="code-quote">"SELECT seq_os_wfentry.nextval FROM dual"</span>/&gt;
+        &lt;property key=<span class="code-quote">"step.sequence"</span> 
+                  value=<span class="code-quote">"SELECT seq_os_currentsteps.nextval FROM dual"</span>/&gt;</pre>
+</div></div>
+
+<p>WAR Deployment<br/>
+-------------<br/>
+To deploy osworkflow_example.war, place it under the directory<br/>
+TOMCAT_HOME/webapps, startup and shutdown the server. Then set up the<br/>
+persistence mechanism as outlined above. Next, modify the server.xml file to<br/>
+configure the data source as outlined above.</p>
+
+<p>Finally, restart the server. Then, go to <br/>
+<a href="http://localhost:8080/osworkflow_example" title="Visit page outside Confluence">&#104;ttp://localhost:8080/osworkflow_example</a> to access the sample application.</p>
+
+<h2><a name="1.3RunningtheExampleApp-Tomcat4.1.x">Tomcat 4.1.x <a name="1.3RunningtheExampleApp-tomcat41"></a>  <a href="#top" title="Visit page outside Confluence">top</a></a></h2>
+
+<p>&lt;Egor Kobylkin egor.kobylkin@o2.com&gt;<br/>
+This is a rough guide on how to deploy osworkflow_example.war on Tomcat 4.1.x. (tested on 4.1.27)</p>
+
+<p>To deploy osworkflow_example.war, place it under the directory<br/>
+TOMCAT_HOME/webapps, startup and shutdown the server. (Ignore if you have already done it)</p>
+
+<p><em>Note that to run the demonstration there is no necessity to create a persistent store - the demonstration will run without it provided that the Tomcat server is not shut down</em></p>
+
+<p><b>Setting up persistence</b></p>
+
+<p>Put jboss-j2ee.jar into TOMCAT_HOME/common/endorsed (get it from JBoss.org) to enable EJB lookup. </p>
+
+<p>Next you have to make modifications to<br/>
+TOMCAT_HOME/conf/server.xml to include:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!-- OSWorkflow JNDI JDBC Data Source Example. egor.kobylkin@o2.com -&gt;</span>
+
+&lt;Context path=<span class="code-quote">"/osworkflow_example"</span> docBase=<span class="code-quote">"osworkflow-2.8.0-example"</span> 
+         debug= <span class="code-quote">"99"</span> reloadable=<span class="code-quote">"true"</span> crossContext=<span class="code-quote">"true"</span> 
+
+verbosity=<span class="code-quote">"DEBUG"</span>&gt;
+&lt;!- debug level is set to paranoid, to know what is happening, 
+     turn it off once you do not need it -&gt;
+
+&lt;Logger className=<span class="code-quote">"org.apache.catalina.logger.FileLogger"</span>
+        prefix=<span class="code-quote">"OSWorkflow."</span> suffix=<span class="code-quote">".log"</span> timestamp=<span class="code-quote">"true"</span>/&gt;
+&lt;!- 
+    put log4j.jar into:
+    TOMCAT_ROOT/webapp/osworkflow-2.8.0-example/WEB-INF/lib 
+    if you want to use it for logging 
+-&gt;
+
+&lt;Resource name=<span class="code-quote">"jdbc/DefaultDS"</span> auth=<span class="code-quote">"Container"</span> 
+                 type=<span class="code-quote">"javax.sql.DataSource"</span>/&gt;
+&lt;!- name=<span class="code-quote">"jdbc/DefaultDS"</span> is used in other components of the 
+     Example App, do not change it here! -&gt;
+
+<span class="code-tag">&lt;ResourceParams name=<span class="code-quote">"jdbc/DefaultDS"</span>&gt;</span>
+  <span class="code-tag">&lt;parameter&gt;</span>
+    <span class="code-tag">&lt;name&gt;</span>factory<span class="code-tag">&lt;/name&gt;</span>
+    <span class="code-tag">&lt;value&gt;</span>org.apache.commons.dbcp.BasicDataSourceFactory<span class="code-tag">&lt;/value&gt;</span>
+  <span class="code-tag">&lt;/parameter&gt;</span>
+  <span class="code-tag">&lt;parameter&gt;</span>
+    <span class="code-tag">&lt;name&gt;</span>driverClassName<span class="code-tag">&lt;/name&gt;</span>
+    <span class="code-tag">&lt;value&gt;</span>oracle.jdbc.driver.OracleDriver<span class="code-tag">&lt;/value&gt;</span>
+  <span class="code-tag">&lt;/parameter&gt;</span>
+  <span class="code-tag">&lt;parameter&gt;</span>
+    <span class="code-tag">&lt;name&gt;</span>url<span class="code-tag">&lt;/name&gt;</span>
+    <span class="code-tag">&lt;value&gt;</span>jdbc:oracle:thin:@yourserver.com:port:SID<span class="code-tag">&lt;/value&gt;</span>
+  <span class="code-tag">&lt;/parameter&gt;</span>
+  <span class="code-tag">&lt;parameter&gt;</span>
+    <span class="code-tag">&lt;name&gt;</span>username<span class="code-tag">&lt;/name&gt;</span>
+    <span class="code-tag">&lt;value&gt;</span>your_database_user_name_here<span class="code-tag">&lt;/value&gt;</span>
+  <span class="code-tag">&lt;/parameter&gt;</span>
+  <span class="code-tag">&lt;parameter&gt;</span>
+    <span class="code-tag">&lt;name&gt;</span>password<span class="code-tag">&lt;/name&gt;</span>
+    <span class="code-tag">&lt;value&gt;</span>your_password_here<span class="code-tag">&lt;/value&gt;</span>
+  <span class="code-tag">&lt;/parameter&gt;</span>
+  <span class="code-tag">&lt;parameter&gt;</span>
+    <span class="code-tag">&lt;name&gt;</span>maxActive<span class="code-tag">&lt;/name&gt;</span>
+    <span class="code-tag">&lt;value&gt;</span>20<span class="code-tag">&lt;/value&gt;</span>
+  <span class="code-tag">&lt;/parameter&gt;</span>
+  <span class="code-tag">&lt;parameter&gt;</span>
+    <span class="code-tag">&lt;name&gt;</span>maxIdle<span class="code-tag">&lt;/name&gt;</span>
+    <span class="code-tag">&lt;value&gt;</span>10<span class="code-tag">&lt;/value&gt;</span>
+  <span class="code-tag">&lt;/parameter&gt;</span>
+  <span class="code-tag">&lt;parameter&gt;</span>
+    <span class="code-tag">&lt;name&gt;</span>maxWait<span class="code-tag">&lt;/name&gt;</span>
+    <span class="code-tag">&lt;value&gt;</span>-1<span class="code-tag">&lt;/value&gt;</span>
+  <span class="code-tag">&lt;/parameter&gt;</span>
+<span class="code-tag">&lt;/ResourceParams&gt;</span>
+<span class="code-tag">&lt;/Context&gt;</span>
+
+<span class="code-tag">&lt;!- OSWorkflow JNDI Data Source -&gt;</span></pre>
+</div></div>
+
+<p>Some documentation on how to configure JNDI / JDBC data sources: </p>
+
+<ul>
+	<li><a href="http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-datasource-examples-howto.html" title="Visit page outside Confluence">&#104;ttp://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-datasource-examples-howto.html</a></li>
+</ul>
+
+
+<ul>
+	<li><a href="http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-resources-howto.html" title="Visit page outside Confluence">&#104;ttp://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-resources-howto.html</a></li>
+</ul>
+
+
+<p>Make sure your JDBC driver is in TOMCAT_HOME/common/lib. For oracle, you may<br/>
+need to rename classes12.zip into classes12.jar for it to work. <br/>
+For Oracle9 DB use only the JDBC thin driver of version 9 or higher. </p>
+
+<p>In addition, modify the osworkflow.xml to reflect how to access sequence<br/>
+objects for your database. <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a> <br/>
+A Description of the entries in osworkflow.xml can be found <a href="http://www.opensymphony.com/osworkflow/api/com/opensymphony/workflow/spi/jdbc/JDBCWorkflowStore.html" title="Visit page outside Confluence">here</a></p>
+
+<p>To use postgresql as the backend database, execute the file tables_postgres.sql<br/>
+against the database and make sure the following is defined in the file<br/>
+osworkflow.xml:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!- Postgresql sequence access -&gt;</span>
+        &lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                        value=<span class="code-quote">"SELECT nextVal('seq_os_wfentry')"</span>/&gt;
+        &lt;property key=<span class="code-quote">"step.sequence"</span> 
+                       value=<span class="code-quote">"SELECT nextVal('seq_os_currentsteps')"</span>/&gt;</pre>
+</div></div>
+
+<p>To use oracle as the backend database, execute the file tables_oracle.sql<br/>
+against the database (watch out for the missing comma in the file) and make  sure the following is defined in the osworkflow.xml file:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;!- Oracle sequence access --&gt;</span>
+        &lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                  value=<span class="code-quote">"SELECT seq_os_wfentry.nextval FROM dual"</span>/&gt;
+        &lt;property key=<span class="code-quote">"step.sequence"</span> 
+                  value=<span class="code-quote">"SELECT seq_os_currentsteps.nextval FROM dual"</span>/&gt;</pre>
+</div></div>
+
+<p>Finally, restart the server. Then, go to:<br/>
+<a href="http://localhost:your_port/osworkflow-2.8.0-example" title="Visit page outside Confluence">&#104;ttp://localhost:your_port/osworkflow-2.8.0-example</a> <br/>
+(or whatever you've mapped the webapp to in your web container) to access <br/>
+the sample application.</p>
+
+<ul>
+	<li>Back to <a href="1.2 Requirements.html" title="1.2 Requirements">1.2 Requirements</a></li>
+	<li>Forward to <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li>
+</ul>
+
 
                     			    </td>
 		    </tr>

docs/1.4 Persistence Options.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <ul class="star">
-<li> Back to <a href="1.3 Running the Example App.html" title="1.3 Running the Example App">1.3 Running the Example App</a></li>
-<li> Forward to <a href="1.5 Loading Workflow Definitions.html" title="1.5 Loading Workflow Definitions">1.5 Loading Workflow Definitions</a></li>
-</ul><br/>
-OSWorkflow provides a pluggable persistence mechanism that can be used to allow for many choices of ways for workflow content to be stored. Included with OSWorkflow are the following WorkflowStore implementations: <b class="strong">MemoryStore (default), SerializableStore, JDBCStore, OfbizStore, and EJBStore</b>. If one of these does not fit your requirements, you can implement your own workflow store by implementing the interface <a href="http://www.opensymphony.com/osworkflow/api/com/opensymphony/workflow/spi/WorkflowStore.html" title="Visit page outside Confluence">com.opensymphony.workflow.spi.WorkflowStore</a>. See the javadocs for more information. <p class="paragraph">Also, please note that each workflow store implementation may have required or optional properties that must or can be set. It is recommend that you read the javadocs for the workflow store that you plan to use so that you can configure it correctly. A sample JDBC configuration for the JDBCStore is given below:</p>(from osworkflow.xml)
-<div class="code"><div class="codeContent">
-<pre>&lt;persistence class=<span class="java&#45;quote">&quot;com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore&quot;</span>&gt;&#10;	&lt;&#33;&#45;&#45; For jdbc persistence, all are required. &#45;&#45;&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;datasource&quot;</span> value=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.sequence&quot;</span> &#10;                      value=<span class="java&#45;quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;wfentry&#039;)&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;WFENTRY&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.id&quot;</span> value=<span class="java&#45;quote">&quot;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.name&quot;</span> value=<span class="java&#45;quote">&quot;NAME&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.state&quot;</span> value=<span class="java&#45;quote">&quot;STATE&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.sequence&quot;</span> &#10;                       value=<span class="java&#45;quote">&quot;SELECT nextVal(&#039;seq&#95;os&#95;currentsteps&#039;)&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;history.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;HISTORYSTEP&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;current.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;CURRENTSTEP&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;historyPrev.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;HISTORYSTEP&#95;PREV&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;currentPrev.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;CURRENTSTEP&#95;PREV&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.id&quot;</span> value=<span class="java&#45;quote">&quot;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.entryId&quot;</span> value=<span class="java&#45;quote">&quot;ENTRY&#95;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.stepId&quot;</span> value=<span class="java&#45;quote">&quot;STEP&#95;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.actionId&quot;</span> value=<span class="java&#45;quote">&quot;ACTION&#95;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.owner&quot;</span> value=<span class="java&#45;quote">&quot;OWNER&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.caller&quot;</span> value=<span class="java&#45;quote">&quot;CALLER&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.startDate&quot;</span> value=<span class="java&#45;quote">&quot;START&#95;DATE&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.finishDate&quot;</span> value=<span class="java&#45;quote">&quot;FINISH&#95;DATE&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.dueDate&quot;</span> value=<span class="java&#45;quote">&quot;DUE&#95;DATE&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.status&quot;</span> value=<span class="java&#45;quote">&quot;STATUS&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.previousId&quot;</span> value=<span class="java&#45;quote">&quot;PREVIOUS&#95;ID&quot;</span>/&gt;&#10;&lt;/persistence&gt;</pre>
-</div></div><p class="paragraph">If you are using tomcat as the servlet container, you should config <b class="strong">$TOMCAT_HOME/conf/server.xml</b> for data source, by default, the data source name is <b class="strong">jdbc/DefaultDS</b>.</p>You should also config the propertyset to use jdbc by adding  <em class="emphasis">WEB-INF/classes/propertyset.xml</em>, please note that the datasource setting should match the name defined in tomcat.
-<div class="code"><div class="codeContent">
-<pre>&lt;propertysets&gt;&#10;    &lt;propertyset name=<span class="java&#45;quote">&quot;jdbc&quot;</span> &#10;      class=<span class="java&#45;quote">&quot;com.opensymphony.module.propertyset.database.JDBCPropertySet&quot;</span>&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;datasource&quot;</span> value=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;table.name&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;PROPERTYENTRY&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;col.globalKey&quot;</span> value=<span class="java&#45;quote">&quot;GLOBAL&#95;KEY&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;col.itemKey&quot;</span> value=<span class="java&#45;quote">&quot;ITEM&#95;KEY&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;col.itemType&quot;</span> value=<span class="java&#45;quote">&quot;ITEM&#95;TYPE&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;col.string&quot;</span> value=<span class="java&#45;quote">&quot;STRING&#95;VALUE&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;col.date&quot;</span> value=<span class="java&#45;quote">&quot;DATE&#95;VALUE&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;col.data&quot;</span> value=<span class="java&#45;quote">&quot;DATA&#95;VALUE&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;col.<span class="java&#45;object">float</span>&quot;</span> value=<span class="java&#45;quote">&quot;FLOAT&#95;VALUE&quot;</span>/&gt;&#10;        &lt;arg name=<span class="java&#45;quote">&quot;col.number&quot;</span> value=<span class="java&#45;quote">&quot;NUMBER&#95;VALUE&quot;</span>/&gt;&#10;    &lt;/propertyset&gt;&#10;&lt;/propertysets&gt;</pre>
-</div></div><p class="paragraph">A number of sample sql scripts to create the required tables are included in the OSWorkflow distribution in in the src/etc/deployment/jdbc directory.</p>If HypersonicSQL is used as the datasource, you can follow these steps:<br/>
+				    <ul>
+	<li>Back to <a href="1.3 Running the Example App.html" title="1.3 Running the Example App">1.3 Running the Example App</a></li>
+	<li>Forward to <a href="1.5 Loading Workflow Definitions.html" title="1.5 Loading Workflow Definitions">1.5 Loading Workflow Definitions</a></li>
+</ul>
+
+
+<p>OSWorkflow provides a pluggable persistence mechanism that can be used to allow for many choices of ways for workflow content to be stored. Included with OSWorkflow are the following WorkflowStore implementations: <b>MemoryStore (default), SerializableStore, JDBCStore, OfbizStore, and EJBStore</b>. If one of these does not fit your requirements, you can implement your own workflow store by implementing the interface <a href="http://www.opensymphony.com/osworkflow/api/com/opensymphony/workflow/spi/WorkflowStore.html" title="Visit page outside Confluence">com.opensymphony.workflow.spi.WorkflowStore</a>. See the javadocs for more information. </p>
+
+<p>Also, please note that each workflow store implementation may have required or optional properties that must or can be set. It is recommend that you read the javadocs for the workflow store that you plan to use so that you can configure it correctly. A sample JDBC configuration for the JDBCStore is given below:</p>
+
+<p>(from osworkflow.xml)</p>
+<div class="code"><div class="codeContent">
+<pre class="code-java">&lt;persistence class=<span class="code-quote">"com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore"</span>&gt;
+	&lt;!-- For jdbc persistence, all are required. --&gt;
+	&lt;property key=<span class="code-quote">"datasource"</span> value=<span class="code-quote">"jdbc/DefaultDS"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                      value=<span class="code-quote">"SELECT nextVal('seq_os_wfentry')"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.table"</span> value=<span class="code-quote">"OS_WFENTRY"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.id"</span> value=<span class="code-quote">"ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.name"</span> value=<span class="code-quote">"NAME"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.state"</span> value=<span class="code-quote">"STATE"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.sequence"</span> 
+                       value=<span class="code-quote">"SELECT nextVal('seq_os_currentsteps')"</span>/&gt;
+	&lt;property key=<span class="code-quote">"history.table"</span> value=<span class="code-quote">"OS_HISTORYSTEP"</span>/&gt;
+	&lt;property key=<span class="code-quote">"current.table"</span> value=<span class="code-quote">"OS_CURRENTSTEP"</span>/&gt;
+	&lt;property key=<span class="code-quote">"historyPrev.table"</span> value=<span class="code-quote">"OS_HISTORYSTEP_PREV"</span>/&gt;
+	&lt;property key=<span class="code-quote">"currentPrev.table"</span> value=<span class="code-quote">"OS_CURRENTSTEP_PREV"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.id"</span> value=<span class="code-quote">"ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.entryId"</span> value=<span class="code-quote">"ENTRY_ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.stepId"</span> value=<span class="code-quote">"STEP_ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.actionId"</span> value=<span class="code-quote">"ACTION_ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.owner"</span> value=<span class="code-quote">"OWNER"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.caller"</span> value=<span class="code-quote">"CALLER"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.startDate"</span> value=<span class="code-quote">"START_DATE"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.finishDate"</span> value=<span class="code-quote">"FINISH_DATE"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.dueDate"</span> value=<span class="code-quote">"DUE_DATE"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.status"</span> value=<span class="code-quote">"STATUS"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.previousId"</span> value=<span class="code-quote">"PREVIOUS_ID"</span>/&gt;
+&lt;/persistence&gt;</pre>
+</div></div>
+
+<p>If you are using tomcat as the servlet container, you should config <b>$TOMCAT_HOME/conf/server.xml</b> for data source, by default, the data source name is <b>jdbc/DefaultDS</b>.</p>
+
+<p>You should also config the propertyset to use jdbc by adding  <em>WEB-INF/classes/propertyset.xml</em>, please note that the datasource setting should match the name defined in tomcat.</p>
+<div class="code"><div class="codeContent">
+<pre class="code-java">&lt;propertysets&gt;
+    &lt;propertyset name=<span class="code-quote">"jdbc"</span> 
+      class=<span class="code-quote">"com.opensymphony.module.propertyset.database.JDBCPropertySet"</span>&gt;
+        &lt;arg name=<span class="code-quote">"datasource"</span> value=<span class="code-quote">"jdbc/DefaultDS"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"table.name"</span> value=<span class="code-quote">"OS_PROPERTYENTRY"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"col.globalKey"</span> value=<span class="code-quote">"GLOBAL_KEY"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"col.itemKey"</span> value=<span class="code-quote">"ITEM_KEY"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"col.itemType"</span> value=<span class="code-quote">"ITEM_TYPE"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"col.string"</span> value=<span class="code-quote">"STRING_VALUE"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"col.date"</span> value=<span class="code-quote">"DATE_VALUE"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"col.data"</span> value=<span class="code-quote">"DATA_VALUE"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"col.<span class="code-object">float</span>"</span> value=<span class="code-quote">"FLOAT_VALUE"</span>/&gt;
+        &lt;arg name=<span class="code-quote">"col.number"</span> value=<span class="code-quote">"NUMBER_VALUE"</span>/&gt;
+    &lt;/propertyset&gt;
+&lt;/propertysets&gt;</pre>
+</div></div>
+
+<p>A number of sample sql scripts to create the required tables are included in the OSWorkflow distribution in in the src/etc/deployment/jdbc directory.</p>
+
+<p>If HypersonicSQL is used as the datasource, you can follow these steps:</p>
+
+<ol>
+	<li>Assume your hsql db is named <b>oswf</b> and created in directory <b>/db</b></li>
+	<li>Use the hsql.sql script to create the tables, you can use <b>java -cp hsqldb.jar org.hsqldb.util.DatabaseManager</b> to startup the tool to execute the sript.</li>
+	<li>Add the context config to <b>$TOMCAT_HOME/conf/server.xml</b></li>
+</ol>
+
+
+<div class="code"><div class="codeContent">
+<pre class="code-java">&lt;Context path=<span class="code-quote">"/osworkflow"</span> 
+         docBase=<span class="code-quote">"/jakarta-tomcat-4.1.27/webapps/osworkflow-2.8.0-example"</span>&gt;
+          &lt;Resource name=<span class="code-quote">"jdbc/oswf"</span> type=<span class="code-quote">"javax.sql.DataSource"</span>/&gt;
+          &lt;ResourceParams name=<span class="code-quote">"jdbc/DefaultDS"</span>&gt;
+            &lt;parameter&gt;&lt;name&gt;username&lt;/name&gt;&lt;value&gt;sa&lt;/value&gt;&lt;/parameter&gt;
+            &lt;parameter&gt;&lt;name&gt;password&lt;/name&gt;&lt;value&gt;&lt;/value&gt;&lt;/parameter&gt;
+            &lt;parameter&gt;&lt;name&gt;driverClassName&lt;/name&gt;
+              &lt;value&gt;org.hsqldb.jdbcDriver&lt;/value&gt;&lt;/parameter&gt;
+            &lt;parameter&gt;&lt;name&gt;url&lt;/name&gt;
+              &lt;value&gt;jdbc:hsqldb:/db/oswf&lt;/value&gt;&lt;/parameter&gt;
+          &lt;/ResourceParams&gt;
+&lt;/Context&gt;</pre>
+</div></div>
+
+<p>4. Add <b>WEB-INF/classes/propertyset.xml</b> as described above</p>
+
+<p>5. Change the persistent setting of <em>WEB-INF/classes/osworkflow.xml</em>. This example below should be used for any database that does not support sequences (eg, HSQL)</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-java">&lt;persistence class=<span class="code-quote">"com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore"</span>&gt;
+	&lt;!- For jdbc persistence, all are required. --&gt;
+	&lt;property key=<span class="code-quote">"datasource"</span> value=<span class="code-quote">"jdbc/DefaultDS"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.sequence"</span> 
+                       value=<span class="code-quote">"select count(*) + 1 from os_wfentry"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.table"</span> value=<span class="code-quote">"OS_WFENTRY"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.id"</span> value=<span class="code-quote">"ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.name"</span> value=<span class="code-quote">"NAME"</span>/&gt;
+	&lt;property key=<span class="code-quote">"entry.state"</span> value=<span class="code-quote">"STATE"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.sequence"</span> value="select sum(c1) from 
+(select 1 tb, count(*) c1 from os_currentstep 
+union select 2 tb, count(*) c1 from os_historystep)"/&gt;
+	&lt;property key=<span class="code-quote">"history.table"</span> value=<span class="code-quote">"OS_HISTORYSTEP"</span>/&gt;
+	&lt;property key=<span class="code-quote">"current.table"</span> value=<span class="code-quote">"OS_CURRENTSTEP"</span>/&gt;
+	&lt;property key=<span class="code-quote">"historyPrev.table"</span> value=<span class="code-quote">"OS_HISTORYSTEP_PREV"</span>/&gt;
+	&lt;property key=<span class="code-quote">"currentPrev.table"</span> value=<span class="code-quote">"OS_CURRENTSTEP_PREV"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.id"</span> value=<span class="code-quote">"ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.entryId"</span> value=<span class="code-quote">"ENTRY_ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.stepId"</span> value=<span class="code-quote">"STEP_ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.actionId"</span> value=<span class="code-quote">"ACTION_ID"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.owner"</span> value=<span class="code-quote">"OWNER"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.caller"</span> value=<span class="code-quote">"CALLER"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.startDate"</span> value=<span class="code-quote">"START_DATE"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.finishDate"</span> value=<span class="code-quote">"FINISH_DATE"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.dueDate"</span> value=<span class="code-quote">"DUE_DATE"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.status"</span> value=<span class="code-quote">"STATUS"</span>/&gt;
+	&lt;property key=<span class="code-quote">"step.previousId"</span> value=<span class="code-quote">"PREVIOUS_ID"</span>/&gt;
+&lt;/persistence&gt;</pre>
+</div></div>
+
+<p>Note that the exact query for step.sequence and entry.sequence might vary in order to use an appropriate sequencing native DB mechanism. </p>
+
+<p>For example, in MSSQL the correct step.sequence value would be (assuming you're not using a database sequence):</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml">&lt;property key=<span class="code-quote">"step.sequence"</span> value="select sum(c1) + 1 from (select 1 as
+tb, count(*) as c1 from os_currentstep union select 2 as tb, count(*) as c1
+from os_historystep) as TabelaFinal" /&gt;</pre>
+</div></div>
+
+<p>For MYSQL, OSWorkflow provides a custom store that can be used. This schema uses a separate table to store ID values (the schema is listed in the mysql.sql file).</p>
+
+<p>In addition to this, two other changes from a standard deployment must be specified. The first are the calls to access the ID sequences. There are specified in the store properties in osworkflow.xml. The elements to be added are:</p>
+<div class="code"><div class="codeContent">
+<pre class="code-xml">&lt;property key=<span class="code-quote">"step.sequence.increment"</span> 
+    value=<span class="code-quote">"INSERT INTO OS_STEPIDS (ID) values (null)"</span>/&gt;
+  &lt;property key=<span class="code-quote">"step.sequence.retrieve"</span> 
+    value=<span class="code-quote">"SELECT max(ID) FROM OS_STEPIDS"</span>/&gt;
+  &lt;property key=<span class="code-quote">"entry.sequence.increment"</span> 
+    value=<span class="code-quote">"INSERT INTO OS_ENTRYIDS (ID) values (null)"</span>/&gt;
+  &lt;property key=<span class="code-quote">"entry.sequence.retrieve"</span> 
+    value=<span class="code-quote">"SELECT max(ID) FROM OS_ENTRYIDS"</span>/&gt;</pre>
+</div></div>
+
+<p>In the same file, the store factory specified should be <b>com.opensymphony.workflow.spi.jdbc.MySQLWorkflowStore</b></p>
+
+<ul>
+	<li>Back to <a href="1.3 Running the Example App.html" title="1.3 Running the Example App">1.3 Running the Example App</a></li>
+	<li>Forward to <a href="1.5 Loading Workflow Definitions.html" title="1.5 Loading Workflow Definitions">1.5 Loading Workflow Definitions</a></li>
+</ul>
 
-<ol>
-<li> Assume your hsql db is named <b class="strong">oswf</b> and created in directory <b class="strong">/db</b></li>
-<li> Use the hsql.sql script to create the tables, you can use <b class="strong">java -cp hsqldb.jar org.hsqldb.util.DatabaseManager</b> to startup the tool to execute the sript.</li>
-<li> Add the context config to <b class="strong">$TOMCAT_HOME/conf/server.xml</b></li>
-</ol>
-<div class="code"><div class="codeContent">
-<pre>&lt;Context path=<span class="java&#45;quote">&quot;/osworkflow&quot;</span> &#10;         docBase=<span class="java&#45;quote">&quot;/jakarta&#45;tomcat&#45;4.1.27/webapps/osworkflow&#45;2.7.0&#45;example&quot;</span>&gt;&#10;          &lt;Resource name=<span class="java&#45;quote">&quot;jdbc/oswf&quot;</span> type=<span class="java&#45;quote">&quot;javax.sql.DataSource&quot;</span>/&gt;&#10;          &lt;ResourceParams name=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>&gt;&#10;            &lt;parameter&gt;&lt;name&gt;username&lt;/name&gt;&lt;value&gt;sa&lt;/value&gt;&lt;/parameter&gt;&#10;            &lt;parameter&gt;&lt;name&gt;password&lt;/name&gt;&lt;value&gt;&lt;/value&gt;&lt;/parameter&gt;&#10;            &lt;parameter&gt;&lt;name&gt;driverClassName&lt;/name&gt;&#10;              &lt;value&gt;org.hsqldb.jdbcDriver&lt;/value&gt;&lt;/parameter&gt;&#10;            &lt;parameter&gt;&lt;name&gt;url&lt;/name&gt;&#10;              &lt;value&gt;jdbc:hsqldb:/db/oswf&lt;/value&gt;&lt;/parameter&gt;&#10;          &lt;/ResourceParams&gt;&#10;&lt;/Context&gt;</pre>
-</div></div><p class="paragraph">4. Add <b class="strong">WEB-INF/classes/propertyset.xml</b> as described above</p>5. Change the persistent setting of <em class="emphasis">WEB-INF/classes/osworkflow.xml</em>. This example below should be used for any database that does not support sequences (eg, HSQL)<br/>
-
-<div class="code"><div class="codeContent">
-<pre>&lt;persistence class=<span class="java&#45;quote">&quot;com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore&quot;</span>&gt;&#10;	&lt;&#33;&#45; For jdbc persistence, all are required. &#45;&#45;&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;datasource&quot;</span> value=<span class="java&#45;quote">&quot;jdbc/DefaultDS&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.sequence&quot;</span> &#10;                       value=<span class="java&#45;quote">&quot;select count&#40;&#42;&#41; &#43; 1 from os&#95;wfentry&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;WFENTRY&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.id&quot;</span> value=<span class="java&#45;quote">&quot;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.name&quot;</span> value=<span class="java&#45;quote">&quot;NAME&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;entry.state&quot;</span> value=<span class="java&#45;quote">&quot;STATE&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.sequence&quot;</span> value=<span class="java&#45;quote">&quot;select sum(c1) from &#10;(select 1 tb, count&#40;&#42;&#41; c1 from os&#95;currentstep &#10;union select 2 tb, count&#40;&#42;&#41; c1 from os&#95;historystep)&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;history.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;HISTORYSTEP&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;current.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;CURRENTSTEP&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;historyPrev.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;HISTORYSTEP&#95;PREV&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;currentPrev.table&quot;</span> value=<span class="java&#45;quote">&quot;OS&#95;CURRENTSTEP&#95;PREV&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.id&quot;</span> value=<span class="java&#45;quote">&quot;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.entryId&quot;</span> value=<span class="java&#45;quote">&quot;ENTRY&#95;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.stepId&quot;</span> value=<span class="java&#45;quote">&quot;STEP&#95;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.actionId&quot;</span> value=<span class="java&#45;quote">&quot;ACTION&#95;ID&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.owner&quot;</span> value=<span class="java&#45;quote">&quot;OWNER&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.caller&quot;</span> value=<span class="java&#45;quote">&quot;CALLER&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.startDate&quot;</span> value=<span class="java&#45;quote">&quot;START&#95;DATE&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.finishDate&quot;</span> value=<span class="java&#45;quote">&quot;FINISH&#95;DATE&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.dueDate&quot;</span> value=<span class="java&#45;quote">&quot;DUE&#95;DATE&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.status&quot;</span> value=<span class="java&#45;quote">&quot;STATUS&quot;</span>/&gt;&#10;	&lt;property key=<span class="java&#45;quote">&quot;step.previousId&quot;</span> value=<span class="java&#45;quote">&quot;PREVIOUS&#95;ID&quot;</span>/&gt;&#10;&lt;/persistence&gt;</pre>
-</div></div><p class="paragraph">Note that the exact query for step.sequence and entry.sequence might vary in order to use an appropriate sequencing native DB mechanism.</p>For example, in MSSQL the correct step.sequence value would be (assuming you&#039;re not using a database sequence):<br/>
-
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;property key=<span class="xml-quote">&quot;step.sequence&quot;</span> value=<span class="xml-quote">&quot;select sum(c1) &#43; 1 from (select 1 as&#10;tb, count&#40;&#42;&#41; as c1 from os&#95;currentstep union select 2 as tb, count&#40;&#42;&#41; as c1&#10;from os&#95;historystep) as TabelaFinal&quot;</span> /&gt;</span></pre>
-</div></div><p class="paragraph">For MYSQL, OSWorkflow provides a custom store that can be used. This schema uses a separate table to store ID values (the schema is listed in the mysql.sql file).</p>In addition to this, two other changes from a standard deployment must be specified. The first are the calls to access the ID sequences. There are specified in the store properties in osworkflow.xml. The elements to be added are:
-<div class="code"><div class="codeContent">
-<pre><span class="xml-tag">&lt;property key=<span class="xml-quote">&quot;step.sequence.increment&quot;</span> &#10;    value=<span class="xml-quote">&quot;INSERT INTO OS&#95;STEPIDS (ID) values (null)&quot;</span>/&gt;</span>&#10;  <span class="xml-tag">&lt;property key=<span class="xml-quote">&quot;step.sequence.retrieve&quot;</span> &#10;    value=<span class="xml-quote">&quot;SELECT max(ID) FROM OS&#95;STEPIDS&quot;</span>/&gt;</span></pre>
-</div></div><p class="paragraph">In the same file, the store factory specified should be <b class="strong">com.opensymphony.workflow.spi.jdbc.MySQLWorkflowStore</b></p><ul class="star">
-<li> Back to <a href="1.3 Running the Example App.html" title="1.3 Running the Example App">1.3 Running the Example App</a></li>
-<li> Forward to <a href="1.5 Loading Workflow Definitions.html" title="1.5 Loading Workflow Definitions">1.5 Loading Workflow Definitions</a></li>
-</ul>
 
                     			    </td>
 		    </tr>

docs/1.5 Loading Workflow Definitions.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <ul class="star">
-<li> Back to <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li>
-<li> Forward to <a href="2. Integration with Other Modules.html" title="2. Integration with Other Modules">2. Integration with Other Modules</a></li>
-</ul><br/>
-OSWorkflow tries to be as flexible as possible with regards to configuration. Only one file is required to be in the classpath: <a href="#osworkflow.xml" title="Visit page outside Confluence">osworkflow.xml</a>. This file dictates the persistence method (JDBC, EJB, Ofbiz) as well the workflow factory class that is to be used for loading workflow definitions. <p class="paragraph">The default factory is <b class="strong">com.opensymphony.workflow.loader.XMLWorkflowFactory</b>. This loads up a file in the classpath that in turn contains links to any number of workflow definition files, all in XML (<a href="http://www.opensymphony.com/osworkflow/workflow_2_6.dtd" title="Visit page outside Confluence">see Appendix A</a>).</p>During test phase it&#039;s also useful to have your workflow definition files reloaded as they are changed. For this you can specify an optional property called <b class="strong">reload</b> (true|false) to your factory definition (default is false). If you would rather specify your workflow definitions in a different way, you are free to extend <a href="http://www.opensymphony.com/osworkflow/api/com/opensymphony/workflow/loader/AbstractWorkflowFactory.html" title="Visit page outside Confluence">com.opensymphony.workflow.loader.AbstractWorkflowFactory</a> in any way that you like. <p class="paragraph"><b class="strong">com.opensymphony.workflow.loader.JDBCWorkflowFactory</b> for example is an alternative factory, that allows you to store your workflow definitions in a JDBC database instead of putting them into the xml files. (<a href="JDBCWorkflowFactory.html" title="JDBCWorkflowFactory">JDBCWorkflowFactory</a>)</p>The most common configuration would be:
-<h3 class="heading3"><a name="1.5LoadingWorkflowDefinitions-%3Caname%3D%221.5LoadingWorkflowDefinitionsosworkflow.xml%22%3E%3C%2Fa%3Eosworkflow.xml%3A"> <a name="1.5LoadingWorkflowDefinitions-osworkflow.xml"></a> osworkflow.xml:</a></h3>
+				    <ul>
+	<li>Back to <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li>
+	<li>Forward to <a href="2. Integration with Other Modules.html" title="2. Integration with Other Modules">2. Integration with Other Modules</a></li>
+</ul>
+
+
+<p>OSWorkflow tries to be as flexible as possible with regards to configuration. Only one file is required to be in the classpath: <a href="#osworkflow.xml" title="Visit page outside Confluence">osworkflow.xml</a>. This file dictates the persistence method (JDBC, EJB, Ofbiz) as well the workflow factory class that is to be used for loading workflow definitions. </p>
+
+<p>The default factory is <b>com.opensymphony.workflow.loader.XMLWorkflowFactory</b>. This loads up a file in the classpath that in turn contains links to any number of workflow definition files, all in XML (<a href="http://www.opensymphony.com/osworkflow/workflow_2_6.dtd" title="Visit page outside Confluence">see Appendix A</a>). </p>
+
+<p>During test phase it's also useful to have your workflow definition files reloaded as they are changed. For this you can specify an optional property called <b>reload</b> (true|false) to your factory definition (default is false). If you would rather specify your workflow definitions in a different way, you are free to extend <a href="http://www.opensymphony.com/osworkflow/api/com/opensymphony/workflow/loader/AbstractWorkflowFactory.html" title="Visit page outside Confluence">com.opensymphony.workflow.loader.AbstractWorkflowFactory</a> in any way that you like. </p>
+
+<p><b>com.opensymphony.workflow.loader.JDBCWorkflowFactory</b> for example is an alternative factory, that allows you to store your workflow definitions in a JDBC database instead of putting them into the xml files. (<a href="JDBCWorkflowFactory.html" title="JDBCWorkflowFactory">JDBCWorkflowFactory</a>)</p>
+
+<p>The most common configuration would be:</p>
+<h3><a name="1.5LoadingWorkflowDefinitions-osworkflow.xml%3A"><a name="1.5LoadingWorkflowDefinitions-osworkflow.xml"></a> osworkflow.xml:</a></h3>
 <div class="code"><div class="codeContent">
-<pre>&lt;osworkflow&gt;&#10;  &lt;persistence class=<span class="java&#45;quote">&quot;com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore&quot;</span>&gt;&#10;    &lt;arg name=<span class="java&#45;quote">&quot;foo&quot;</span> value=<span class="java&#45;quote">&quot;bar&quot;</span>/&gt;&#10;    ...&#10;  &lt;/persistence&gt;&#10;  &lt;factory class=<span class="java&#45;quote">&quot;com.opensymphony.workflow.loader.XMLWorkflowFactory&quot;</span>&gt;&#10;    &lt;property key=<span class="java&#45;quote">&quot;resource&quot;</span> value=<span class="java&#45;quote">&quot;workflows.xml&quot;</span> /&gt;&#10;  &lt;/factory&gt;&#10;&lt;/osworkflow&gt;</pre>
+<pre class="code-java">&lt;osworkflow&gt;
+  &lt;persistence class=<span class="code-quote">"com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore"</span>&gt;
+    &lt;arg name=<span class="code-quote">"foo"</span> value=<span class="code-quote">"bar"</span>/&gt;
+    ...
+  &lt;/persistence&gt;
+  &lt;factory class=<span class="code-quote">"com.opensymphony.workflow.loader.XMLWorkflowFactory"</span>&gt;
+    &lt;property key=<span class="code-quote">"resource"</span> value=<span class="code-quote">"workflows.xml"</span> /&gt;
+  &lt;/factory&gt;
+&lt;/osworkflow&gt;</pre>
 </div></div>
-<h3 class="heading3"><a name="1.5LoadingWorkflowDefinitions-%3Caname%3D%221.5LoadingWorkflowDefinitionsworkflows.xml%22%3E%3C%2Fa%3Eworkflows.xml%3A"> <a name="1.5LoadingWorkflowDefinitions-workflows.xml"></a> workflows.xml:</a></h3>
+<h3><a name="1.5LoadingWorkflowDefinitions-workflows.xml%3A"><a name="1.5LoadingWorkflowDefinitions-workflows.xml"></a> workflows.xml:</a></h3>
+
+<div class="code"><div class="codeContent">
+<pre class="code-java">&lt;workflows&gt;
+  &lt;workflow name=<span class="code-quote">"example"</span> type=<span class="code-quote">"resource"</span> location=<span class="code-quote">"example.xml"</span>/&gt;
+&lt;/workflows&gt;</pre>
+</div></div>
+
+<ul>
+	<li>Back to <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li>
+	<li>Forward to <a href="2. Integration with Other Modules.html" title="2. Integration with Other Modules">2. Integration with Other Modules</a></li>
+</ul>
 
-<div class="code"><div class="codeContent">
-<pre>&lt;workflows&gt;&#10;  &lt;workflow name=<span class="java&#45;quote">&quot;example&quot;</span> type=<span class="java&#45;quote">&quot;resource&quot;</span> location=<span class="java&#45;quote">&quot;example.xml&quot;</span>/&gt;&#10;&lt;/workflows&gt;</pre>
-</div></div><br/>
-
-<ul class="star">
-<li> Back to <a href="1.4 Persistence Options.html" title="1.4 Persistence Options">1.4 Persistence Options</a></li>
-<li> Forward to <a href="2. Integration with Other Modules.html" title="2. Integration with Other Modules">2. Integration with Other Modules</a></li>
-</ul>
 
                     			    </td>
 		    </tr>

docs/2. Integration with Other Modules.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <ul class="star">
-<li> Back to <a href="1.5 Loading Workflow Definitions.html" title="1.5 Loading Workflow Definitions">1.5 Loading Workflow Definitions</a></li>
-<li> Forward to <a href="3. Understanding OSWorkflow.html" title="3. Understanding OSWorkflow">3. Understanding OSWorkflow</a></li>
+				    <ul>
+	<li>Back to <a href="1.5 Loading Workflow Definitions.html" title="1.5 Loading Workflow Definitions">1.5 Loading Workflow Definitions</a></li>
+	<li>Forward to <a href="2.3 Spring framework.html" title="2.3 Spring framework">2.3 Spring framework</a></li>
 </ul>
-<h3 class="heading3"><a name="2.IntegrationwithOtherModules-IntegrationwithOSCore"> Integration with OSCore</a></h3><p class="paragraph">OSWorkflow requires <a href="http://www.opensymphony.com/propertyset" title="Visit page outside Confluence">PropertySet</a>, and <a href="http://www.opensymphony.com/oscore" title="Visit page outside Confluence">OSCore</a>. Furthermore, OSWorkflow makes heavy usage of the many useful features in OSCore, and therefore OSCore version 2.2.0 or above is required to use OSWorkflow. OSUser is not strictly required, however, all of the built-in user/group functions and conditions use it, so you should include it unless you plan on writing your own versions of those conditions.
-<h3 class="heading3"><a name="2.IntegrationwithOtherModules-IntegrationwithPropertySet"> Integration with PropertySet</a></h3></p>One of the key features in OSWorkflow is the ability to save variables dynamically. This allows for a function (see <a href="3.4 Functions.html" title="3.4 Functions">3.4 Functions</a>) to take place on day 1 in the workflow lifecycle and store a piece of data in OSWorkflow. Then, many days later, when an action is executed in the workflow, that same data can be pulled up and re-used in another function. This is a very powerful feature that when used properly can allow for highly customized, long-lived workflow behavior that persists even after server restarts.<p class="paragraph">This is all possible by using the <a href="http://www.opensymphony.com/propertyset" title="Visit page outside Confluence">PropertySet</a> module. What kinds of variable types you can dynamically store in the propertyset (usually exposed as the variable <b class="strong">ps</b>) is totally up to the PropertySet implementation that is chosen by the <b class="strong">WorkflowStore</b> you have configured in <em class="emphasis">osworkflow.xml</em>. For example, if you choose the <em class="emphasis">JDBCWorkflowStore</em>, you must make sure that the jdbc propertyset is properly configured in <em class="emphasis">propertyset.xml</em>. Information on setting up the propertyset backend store (for example, sql scripts for the JDBCPropertySet) can be found in the propertyset download.</p>
+
+
+<h3><a name="2.IntegrationwithOtherModules-IntegrationwithOSCore">Integration with OSCore</a></h3>
+
+<p>OSWorkflow requires <a href="http://www.opensymphony.com/propertyset" title="Visit page outside Confluence">PropertySet</a>, and <a href="http://www.opensymphony.com/oscore" title="Visit page outside Confluence">OSCore</a>. Furthermore, OSWorkflow makes heavy usage of the many useful features in OSCore, and therefore OSCore version 2.2.0 or above is required to use OSWorkflow. OSUser is not strictly required, however, all of the built-in user/group functions and conditions use it, so you should include it unless you plan on writing your own versions of those conditions.</p>
+<h3><a name="2.IntegrationwithOtherModules-IntegrationwithPropertySet">Integration with PropertySet</a></h3>
+
+<p>One of the key features in OSWorkflow is the ability to save variables dynamically. This allows for a function (see <a href="3.4 Functions.html" title="3.4 Functions">3.4 Functions</a>) to take place on day 1 in the workflow lifecycle and store a piece of data in OSWorkflow. Then, many days later, when an action is executed in the workflow, that same data can be pulled up and re-used in another function. This is a very powerful feature that when used properly can allow for highly customized, long-lived workflow behavior that persists even after server restarts.</p>
+
+<p>This is all possible by using the <a href="http://www.opensymphony.com/propertyset" title="Visit page outside Confluence">PropertySet</a> module. What kinds of variable types you can dynamically store in the propertyset (usually exposed as the variable <b>ps</b>) is totally up to the PropertySet implementation that is chosen by the <b>WorkflowStore</b> you have configured in <em>osworkflow.xml</em>. For example, if you choose the <em>JDBCWorkflowStore</em>, you must make sure that the jdbc propertyset is properly configured in <em>propertyset.xml</em>. Information on setting up the propertyset backend store (for example, sql scripts for the JDBCPropertySet) can be found in the propertyset download.</p>
 
                     			    </td>
 		    </tr>

docs/2. Testing your workflow - Chinese.html

 	    <table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%" bgcolor="#ffffff">
 		    <tr>
 			    <td valign="top" class="pagebody">
-				    <p class="paragraph">现在我们已经完成了一个完整的工作流定义,下一步是检验它是否按照我们预想的方式执行。</p>在一个快速开发环境中,最简单的方法就是写一个测试案例。通过测试案例调用工作流,根据校验结果和捕捉可能发生的错误,来保证流程定义的正确性。<p class="paragraph">我们假设你已经熟悉Junit和了解怎样编写测试案例。如果你对这些知识还不了解的话,可以去JUnit的网站查找、阅读相关文档。编写测试案例会成为你的一个非常有用的工具。</p>在开始载入流程定义、调用动作以前,我们需要配置OSWorkflow的数据存储方式和定义文件的位置等。<p class="paragraph">h3 配置 osworkflow.xml</p>我们需要创建的第一个文件是 <em class="emphasis">osworkflow.xml</em>。下面是一个简单的例子:<br/>
+				    <p>现在我们已经完成了一个完整的工作流定义,下一步是检验它是否按照我们预想的方式执行。</p>
+
+<p>在一个快速开发环境中,最简单的方法就是写一个测试案例。通过测试案例调用工作流,根据校验结果和捕捉可能发生的错误,来保证流程定义的正确性。</p>
+
+<p>我们假设你已经熟悉Junit和了解怎样编写测试案例。如果你对这些知识还不了解的话,可以去JUnit的网站查找、阅读相关文档。编写测试案例会成为你的一个非常有用的工具。</p>
+
+<p>在开始载入流程定义、调用动作以前,我们需要配置OSWorkflow的数据存储方式和定义文件的位置等。</p>
+
+<p>h3 配置 osworkflow.xml</p>
+
+<p>我们需要创建的第一个文件是 <em>osworkflow.xml</em>。下面是一个简单的例子:</p>
+
+<div class="code"><div class="codeContent">
+<pre class="code-xml"><span class="code-tag">&lt;osworkflow&gt;</span>
+  <span class="code-tag">&lt;persistence class=<span class="code-quote">"com.opensymphony.workflow.spi.memory.MemoryWorkflowStore"</span>/&gt;</span>
+  <span class="code-tag">&lt;factory class=<span class="code-quote">"com.opensymphony.workflow.loader.XMLWorkflowFactory"</span>&gt;</span>
+    <span class="code-tag">&lt;property key=<span class="code-quote">"resource"</span> value=<span class="code-quote">"workflows.xml"</span> /&gt;</span>
+  <span class="code-tag">&lt;/factory&gt;</span> 
+<span class="code-tag">&lt;/osworkflow&gt;</span></pre>
+</div></div>
+
+<p>这个例子指明了我们准备使用内存 (MemoryWorkflowStore) 来保存流程数据。这样可以减少设置数据库的相关信息,减少出问题的可能性。用内存持久化对于测试来说是非常方便的。</p>
+
+<p>h3 Workflow factories</p>
+
+<p>上面的配置文件还指明了我们工作流工厂(XMLWorkflowFactory),工作流工厂的主要功能是管理流程定义文件,包括读取定义文件和修改定义文件的功能。通过'resource'这个属性指明了采用通过从classpath中读取流程定义文件的方式,按照这个定义,接下来我们需要在classpath中创建一个名为workflows.xml的文件。</p>
+