OSWorkflow的第一支程式
|
(史帝芬, 2005/6/4, [email protected]) |
自從C的聖經版以Hello World程式開始引導初學者學習程式語言以來,多數的程式語言入門書也都如法刨製。 OSWorkflow沒辦法寫出那種一目瞭然的程式,但是我仍盡量將程式簡化,希望初學者能在看完這第一支程式後, 就能有所體會。接下來將講解如何寫出第一支OSWorkflow程式!
將以下jar file放置到WEB-INF/lib底下… activation.jar bsh-1.2b7.jar commons-logging.jar designer.jar mail.jar oscore-2.2.2.jar osuser-1.0-dev-3Dec03.jar osworkflow-2.7.0.jar propertyset-1.3-21Apr04.jar quartz.jar 這些jar file可以在OSWorkflow提供的example裡找到。 在SQL Server中建立一資料庫,名稱可自取,這裡取名OSWorkflow,然後執行%OSWorkflow%/src/etc/deployment/jdbc/mssql.sql, 建立OSWorkflow所需的Table。 然後在Tomcat設定DataSource取名jdbc/DefaultDS並指向資料庫OSWorkflow,方法可參考 Connection Pool (2)。 接下來將以下內容放入osworkflow.xml,並將osworkflow.xml放置在WEB-INF/classes底下。 <osworkflow> 建立一個命名為leave.xml的檔案,並將它放入WEB-INF/classes底下,檔名可自取,這個檔案就是記載流程的檔案。 <?xml version="1.0" encoding="UTF-8" ?>接著在workflows.xml中加入如下的設定,即可讓系統於啟動後載入請假的流程,workflows.xml也放至WEB-INF/classes。 <workflows> 這裡將建立兩個網頁分別給員工和主管使用,另外有兩個servlet及一個類別作為趨動流程。 Leave.java package tw.idv.idealist;LeaveAction.java (servlet) package tw.idv.idealist.actions;AllowAction.java (servlet) package tw.idv.idealist.actions;leave.jsp <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">allow.jsp <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 啟動Tomcat,並執行leave.jsp,按"送出"後,假單即送出,接著會出現allow.jsp的網頁供主管簽核,主管按"淮許"後, 請假流程即完成,記得在執行過程中多觀察資料庫中資料的變化。 請假 准假 |
OSWorkflow 觀念探討(1) -- 流程設定基礎
( 史帝芬, 2005/6/6 , [email protected])
看完第一支程式,相信讀者會有許多疑問,這些先就流程的設定做初步的介紹。首先,讀者應該注意到了, 第一支程式的用到三個xml設定檔,沒錯,這三個是設定流程的設定檔。
- osworkflow.xml :這個檔案是設定流程是否存在資料庫或存在記憶體,前面的內容是存在MS SQL Server的寫法。
- leave.xml :請假流程寫在這個檔案,這也是osworkflow的重點之一。
- workflows.xml :指定系統啟動時要載入那些流程。
這裡針對leave.xml做些說明…
- initial-actions :每個流程都至少需定義一個initial-actions,這是流程的起點。
- action :導致流程變動的動作,每個action都有個編號,且不能重複。
- step :雖然它的名稱是步驟,似乎它會有動作? 其實將它視為流程位置可能比較恰當,osworkflow真正的動作在action發生。
- result :執行動作後的結果,result有兩種conditional-result和unconditional-result,每個result一定有unconditional-result, 當conditional-result的條件都不滿足時,就執行unconditional-result。
- status :流程在某個action時的狀態。
- old-status :流程執行某個action後的狀態。
- caller :這是OSWorkflow的保留字,可取得呼叫此工作流的user,即Workflow workflow = new BasicWorkflow(caller); 在資料庫中會記錄於Table OS_HISTORYSTEP如下:
記得在pre-functions加上如下設定…
<pre-functions>
<function type="class">
<arg name="class.name">com.opensymphony.workflow.util.Caller</arg>
</function>
</pre-functions>
- owner :這是傳工作流到此步驟的user。
OSWorkflow 的第二支程式 |
||||||||||||||||||
( 史帝芬, 2005/6/11 , [email protected]) |
||||||||||||||||||
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN" "http://www.opensymphony.com/osworkflow/workflow_2_7.dtd"> <workflow> <initial-actions> <action id="0" name=" 開始"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="1" owner="${caller}" /> </results> </action> </initial-actions>
<steps> <step id="1" name=" 填假單"> <actions> <action id="1" name=" 送出"> <restrict-to> <conditions> <condition type="class"> <arg name="class.name"> com.opensymphony.workflow.util.AllowOwnerOnlyCondition </arg> </condition> </conditions> </restrict-to> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="2" owner="${caller}" /> </results> </action> </actions> </step>
<step id="2" name=" 批假單"> <actions> <action id="2" name=" 准許"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="3" owner="${caller}"/> </results> </action>
<action id="3" name=" 駁回"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="1" owner="${caller}"/> </results> </action> </actions> </step>
<step id="3" name=" 停止" /> </steps> </workflow> 接著更改Leave.java及LeaveAction.java,讓啟動流程的人和送出假單的人可以不同。 package tw.idv.idealist;
import com.opensymphony.workflow.InvalidActionException; import com.opensymphony.workflow.InvalidEntryStateException; import com.opensymphony.workflow.InvalidInputException; import com.opensymphony.workflow.InvalidRoleException; import com.opensymphony.workflow.Workflow; import com.opensymphony.workflow.WorkflowException; import com.opensymphony.workflow.basic.BasicWorkflow; import com.opensymphony.workflow.config.DefaultConfiguration; import com.opensymphony.workflow.spi.Step;
/** * 請假流程 * @author steven */ public class Leave { /** * 啟動流程 * @param employee 員工編號 * @return 工作流編號 */ public long start(String employee) { Workflow workflow = new BasicWorkflow(employee); DefaultConfiguration config = new DefaultConfiguration(); workflow.setConfiguration(config); long workflowId = -1; try { //leave 是workflowx.xml中定的名稱 workflowId = workflow.initialize("leave", 0, null); } catch (InvalidActionException e) { e.printStackTrace(); } catch (InvalidRoleException e) { e.printStackTrace(); } catch (InvalidInputException e) { e.printStackTrace(); } catch (InvalidEntryStateException e) { e.printStackTrace(); } catch (WorkflowException e) { e.printStackTrace(); }
return workflowId; }
/** * 送出假單 * @param workflowId 工作流編號 * @param employee 員工編號 */ public void send(long workflowId, String employee) { Workflow workflow = new BasicWorkflow(employee); DefaultConfiguration config = new DefaultConfiguration(); workflow.setConfiguration(config); try { workflow.doAction(workflowId, 1, null); } catch (InvalidActionException e) { e.printStackTrace(); } catch (InvalidRoleException e) { e.printStackTrace(); } catch (InvalidInputException e) { e.printStackTrace(); } catch (InvalidEntryStateException e) { e.printStackTrace(); } catch (WorkflowException e) { e.printStackTrace(); } }
/** * 准假假單 * @param workflowId 工作流編號 * @param actionId 動作編號, 2 准許, 3 駁回 */ public void allow(long workflowId, int actionId) { Workflow workflow = new BasicWorkflow("manager1"); DefaultConfiguration config = new DefaultConfiguration(); workflow.setConfiguration(config); try { workflow.doAction(workflowId, actionId, null); } catch (InvalidInputException e) { e.printStackTrace(); } catch (WorkflowException e) { e.printStackTrace(); } catch (InvalidActionException e) { e.printStackTrace(); } } } LeaveAction.java package tw.idv.idealist.actions;
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import tw.idv.idealist.Leave;
/** * @author Steven */ public class LeaveAction extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); }
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Leave leave = new Leave(); String employee = req.getParameter("employee"); long workflowId = leave.start(employee); leave.send(workflowId, "someone"); // <<== 非啟動流程的人送出假單 resp.sendRedirect("allow.jsp?workflowId=" + workflowId); }
} package tw.idv.idealist.actions;
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import tw.idv.idealist.Leave;
/** * @author Steven */ public class LeaveAction extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); }
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Leave leave = new Leave(); String employee = req.getParameter("employee"); long workflowId = leave.start(employee); leave.send(workflowId, "someone"); // <<== 非啟動流程的人送出假單 resp.sendRedirect("allow.jsp?workflowId=" + workflowId); }
} 啟動Tomcat,並執行leave.jsp後,會出現如下exception,確實OSWorkflow偵測到啟動流程的人和送出假單的人不同。 com.opensymphony.workflow.InvalidActionException: Action 1 is invalid at com.opensymphony.workflow.AbstractWorkflow.doAction(AbstractWorkflow.java:546) at tw.idv.idealist.Leave.send(Leave.java:56) at tw.idv.idealist.actions.LeaveAction.doPost(LeaveAction.java:25) at tw.idv.idealist.actions.LeaveAction.doGet(LeaveAction.java:17) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2422) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:163) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:199) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:828) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:700) at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:584) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683) at java.lang.Thread.run(Thread.java:534) |
||||||||||||||||||
OSWorkflow 觀念探討(2) -- 限制條件 |
||||||||||||||||||
( 史帝芬, 2005/6/11 , [email protected]) |
||||||||||||||||||
當同時要加上兩個限制條件時,可以如下寫。 <restrict-to> <conditions type="AND"> <condition type="class"> <arg name="class.name"> com.opensymphony.workflow.util.StatusCondition </arg> <arg name="status">Queued</arg> </condition> <condition type="class"> <arg name="class.name"> com.opensymphony.workflow.util.OSUserGroupCondition </arg> <arg name="group">A0001</arg> </condition> </conditions> </restrict-to> |
||||||||||||||||||
OSWorkflow 的第三支程式 |
||||||||||||||||||
( 史帝芬, 2005/6/11 , [email protected]) |
||||||||||||||||||
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN" "http://www.opensymphony.com/osworkflow/workflow_2_7.dtd"> <workflow> <initial-actions> <action id="0" name=" 開始"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> <function type="beanshell"> <arg name="script"> propertySet.setString("type", transientVars.get("type")); </arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="1" owner="${caller}" /> </results> <post-functions> <function type="class"> <arg name="class.name"> tw.idv.idealist.OutputPropertySet </arg> <arg name="author">Steven Shi</arg> </function> </post-functions> </action> </initial-actions>
<steps> <step id="1" name=" 填假單"> <actions> <action id="1" name=" 送出"> <restrict-to> <conditions> <condition type="class"> <arg name="class.name"> com.opensymphony.workflow.util.AllowOwnerOnlyCondition </arg> </condition> </conditions> </restrict-to> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="2" owner="${caller}" /> </results> </action> </actions> </step>
<step id="2" name=" 批假單"> <actions> <action id="2" name=" 准許"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="3" owner="${caller}"/> </results> </action>
<action id="3" name=" 駁回"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="1" owner="${caller}"/> </results> </action> </actions> </step>
<step id="3" name=" 停止" /> </steps> </workflow> leave.jsp <!DOCTYPE HTML PUBLIC "-//W 3C //DTD HTML 4.01 Transitional//EN">
<HTML> <HEAD> <%@ page language="java" contentType="text/html; charset=BIG5" pageEncoding="BIG5" %> <%@ page import="tw.idv.idealist.*" %>
< META http-equiv="Content-Type" content="text/html; charset=BIG5"> < META http-equiv="Content-Style-Type" content="text/css"> <TITLE> 填寫假單</TITLE> <Script Language="JavaScript"> function DoAction(type) { document.myForm.type.value = type; document.myForm.submit(); } </Script> </HEAD> <BODY> <P> 員工請假</P>
<form name="myForm" action="LeaveAction"> <input type="hidden" name="type" value=""> 員工代號: <input type="text" name="employee"><br> <input type="button" value=" 事假" OnClick="DoAction(1)"> <input type="button" value=" 病假" OnClick="DoAction(2)"> </form>
</BODY> </HTML> Leave.java package tw.idv.idealist;
import java.util.HashMap; import com.opensymphony.workflow.*; import com.opensymphony.workflow.basic.BasicWorkflow; import com.opensymphony.workflow.config.DefaultConfiguration; import com.opensymphony.workflow.spi.Step;
/** * 請假流程 * @author steven */ public class Leave { /** * 啟動流程 * @param employee 員工編號 * @param type 假別 * @return 工作流編號 */ public long start(String employee, String type) { Workflow workflow = new BasicWorkflow(employee); DefaultConfiguration config = new DefaultConfiguration(); workflow.setConfiguration(config); long workflowId = -1; try { HashMap map = new HashMap(); map.put("type", type); //leave 是workflowx.xml中定的名稱 workflowId = workflow.initialize("leave", 0, map); } catch (InvalidActionException e) { e.printStackTrace(); } catch (InvalidRoleException e) { e.printStackTrace(); } catch (InvalidInputException e) { e.printStackTrace(); } catch (InvalidEntryStateException e) { e.printStackTrace(); } catch (WorkflowException e) { e.printStackTrace(); }
return workflowId; }
/** * 送出假單 * @param workflowId 工作流編號 * @param employee 員工編號 */ public void send(long workflowId, String employee) { Workflow workflow = new BasicWorkflow(employee); DefaultConfiguration config = new DefaultConfiguration(); workflow.setConfiguration(config); try { workflow.doAction(workflowId, 1, null); } catch (InvalidActionException e) { e.printStackTrace(); } catch (InvalidRoleException e) { e.printStackTrace(); } catch (InvalidInputException e) { e.printStackTrace(); } catch (InvalidEntryStateException e) { e.printStackTrace(); } catch (WorkflowException e) { e.printStackTrace(); } }
/** * 准假假單 * @param workflowId 工作流編號 * @param actionId 動作編號, 2 准許, 3 駁回 */ public void allow(long workflowId, int actionId) { Workflow workflow = new BasicWorkflow("manager1"); DefaultConfiguration config = new DefaultConfiguration(); workflow.setConfiguration(config); try { workflow.doAction(workflowId, actionId, null); } catch (InvalidInputException e) { e.printStackTrace(); } catch (WorkflowException e) { e.printStackTrace(); } catch (InvalidActionException e) { e.printStackTrace(); } } } LeavaAction.java package tw.idv.idealist.actions;
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import tw.idv.idealist.Leave;
/** * @author Steven */ public class LeaveAction extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doPost(req, resp); }
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Leave leave = new Leave(); String employee = req.getParameter("employee"); String type = req.getParameter("type"); long workflowId = leave.start(employee, type); leave.send(workflowId, employee); resp.sendRedirect("allow.jsp?workflowId=" + workflowId); }
} OutputPropertySet.java package tw.idv.idealist;
import java.util.Map;
import com.opensymphony.module.propertyset.PropertySet; import com.opensymphony.workflow.FunctionProvider; import com.opensymphony.workflow.WorkflowException;
/** * @author steven */ public class OutputPropertySet implements FunctionProvider { public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException { if (ps.getString("type").equals("1")) { System.out.println(" 事假"); } else if (ps.getString("type").equals("2")) { System.out.println(" 病假"); } System.out.println("author => " + args.get("author")); } }
病假 author => Steven Shi 資料庫Table OS_PROPERTYENTRY則出現如下的值,可以看到假別已存入資料庫。 |
||||||||||||||||||
OSWorkflow 觀念探討(3) -- 傳值儲值 |
||||||||||||||||||
( 史帝芬, 2005/6/11 , [email protected]) |
||||||||||||||||||
<function type="class"> <arg name="class.name"> tw.idv.idealist.OutputPropertySet </arg> <arg name="author">Steven Shi</arg> </function> |
||||||||||||||||||
OSWorkflow 的第四支程式 |
||||||||||||||||||
( 史帝芬, 2005/6/11 , [email protected]) |
||||||||||||||||||
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE workflow PUBLIC "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN" "http://www.opensymphony.com/osworkflow/workflow_2_7.dtd"> <workflow> <initial-actions> <action id="0" name=" 開始"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> <function type="beanshell"> <arg name="script"> propertySet.setString("type", transientVars.get("type")); propertySet.setString("employee", transientVars.get("caller")); </arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="1" owner="${caller}" /> </results> <post-functions> <function type="class"> <arg name="class.name"> tw.idv.idealist.OutputPropertySet </arg> <arg name="author">Steven Shi</arg> </function> </post-functions> </action> </initial-actions>
<steps> <step id="1" name=" 填假單"> <actions> <action id="1" name=" 送出"> <restrict-to> <conditions> <condition type="class"> <arg name="class.name"> com.opensymphony.workflow.util.AllowOwnerOnlyCondition </arg> </condition> </conditions> </restrict-to> <validators> <validator type="class"> <arg name="class.name"> tw.idv.idealist.MyValidator </arg> </validator> </validators> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="2" owner="${caller}" /> </results> </action> </actions> </step>
<step id="2" name=" 批假單"> <actions> <action id="2" name=" 准許"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="3" owner="${caller}"/> </results> </action>
<action id="3" name=" 駁回"> <pre-functions> <function type="class"> <arg name="class.name">com.opensymphony.workflow.util.Caller</arg> </function> </pre-functions> <results> <unconditional-result old-status="Finished" status="Queued" step="1" owner="${caller}"/> </results> </action> </actions> </step>
<step id="3" name=" 停止" /> </steps> </workflow> MyValidator.java package tw.idv.idealist;
import java.util.Map; import com.opensymphony.module.propertyset.PropertySet; import com.opensymphony.workflow.InvalidInputException; import com.opensymphony.workflow.Validator; import com.opensymphony.workflow.WorkflowException;
/** * @author steven */ public class MyValidator implements Validator {
public void validate(Map transientVars, Map args, PropertySet ps) throws InvalidInputException, WorkflowException { if (ps.getString("employee").length() != 4) { throw new InvalidInputException(" 員工編號錯誤"); } }
}
[InvalidInputException: [Error map: [{}]] [Error list: [[ 員工編號錯誤]]] at tw.idv.idealist.MyValidator.validate(MyValidator.java:17) at com.opensymphony.workflow.AbstractWorkflow.verifyInputs(AbstractWorkflow.java:1025) at com.opensymphony.workflow.AbstractWorkflow.transitionWorkflow(AbstractWorkflow.java:1248) at com.opensymphony.workflow.AbstractWorkflow.doAction(AbstractWorkflow.java:551) at tw.idv.idealist.Leave.send(Leave.java:55) at tw.idv.idealist.actions.LeaveAction.doPost(LeaveAction.java:26) at tw.idv.idealist.actions.LeaveAction.doGet(LeaveAction.java:17) at javax.servlet.http.HttpServlet.service(HttpServlet.java:740) at javax.servlet.http.HttpServlet.service(HttpServlet.java:853) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:247) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:256) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardContext.invoke(StandardContext.java:2422) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:180) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.valves.ErrorDispatcherValve.invoke(ErrorDispatcherValve.java:171) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:163) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:641) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:174) at org.apache.catalina.core.StandardPipeline$StandardPipelineValveContext.invokeNext(StandardPipeline.java:643) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:480) at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:995) at org.apache.coyote.tomcat4.CoyoteAdapter.service(CoyoteAdapter.java:199) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:828) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:700) at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:584) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683) at java.lang.Thread.run(Thread.java:534) |
||||||||||||||||||
OSWorkflow 觀念探討(4) -- 校驗器 |
||||||||||||||||||
( 史帝芬, 2005/6/11 , [email protected]) |
||||||||||||||||||
<validators> <validator type="class"> <arg name="class.name"> tw.idv.idealist.MyValidator </arg> </validator> </validators> 上面這一段設定應放在那裡? 這可以查一下DTD,就知道應放於那個位置了。 |
||||||||||||||||||
OSWorkflow 的第五支程式 |
||||||||||||||||||
( 史帝芬, 2005/6/11 , [email protected]) |
||||||||||||||||||
package tw.idv.idealist;
import java.util.*; import com.opensymphony.workflow.*; import com.opensymphony.workflow.query.*; import com.opensymphony.workflow.spi.WorkflowEntry;
/** * @author steven */ public class Query extends AbstractWorkflow { public List getCompleted() { FieldExpression fe = new FieldExpression(FieldExpression.STATE, FieldExpression.ENTRY, FieldExpression.EQUALS, new Integer(WorkflowEntry.COMPLETED)); List list = null; try { list = getPersistence().query(new WorkflowExpressionQuery(fe)); } catch (StoreException e) { e.printStackTrace(); }
return list; } } completed.jsp <!DOCTYPE HTML PUBLIC "-//W 3C //DTD HTML 4.01 Transitional//EN">
<HTML> <HEAD> <%@ page language="java" contentType="text/html; charset=BIG5" pageEncoding="BIG5" %> <%@ page import="tw.idv.idealist.*" %> <%@ page import="java.util.*" %>
< META http-equiv="Content-Type" content="text/html; charset=BIG5"> < META http-equiv="Content-Style-Type" content="text/css"> <LINK href="theme/Master.css" rel="stylesheet"type="text/css"> <TITLE>completed.jsp</TITLE> </HEAD> <BODY>
已完成的工作流編號:<br> <% Query query = new Query(); List completed = query.getCompleted(); for(int i=0; i<completed.size(); i++) { Long wfId = (Long) completed.get(i); out.println("workflow id => " + wfId + "<br>"); } %>
</BODY> </HTML>
|
||||||||||||||||||
OSWorkflow 觀念探討(5) -- 查詢API |
||||||||||||||||||
( 史帝芬, 2005/6/11 , [email protected]) |
||||||||||||||||||
// Get all finished workflow entries //where the current owner is 'testuser' Expression queryLeft = new FieldExpression( FieldExpression.OWNER, FieldExpression.CURRENT_STEPS, FieldExpression.EQUALS, 'testuser'); Expression queryRight = new FieldExpression( FieldExpression.STATUS, FieldExpression.CURRENT_STEPS, FieldExpression.EQUALS, "Finished", true); WorkflowExpressionQuery query = new WorkflowExpressionQuery( new NestedExpression( new Expression[] {queryLeft, queryRight}, NestedExpression.AND));
|