OSWorkflow的第一支程式


OSWorkflow的第一支程式

(史帝芬, 2005/6/4,) 


自从C的圣经版以Hello World程式开始引导初学者学习程式语言以来,多数的程式语言入门书也都如法刨制。 OSWorkflow没办法写出那种一目了然的程式,但是我仍尽量将程式简化,希望初学者能在看完这第一支程式后,就能有所体会。接下来将讲解如何写出第一支OSWorkflow程式!



jar file


將以下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> 
 
<!-- 
 
<persistence class="com.opensymphony.workflow.spi.memory.MemoryWorkflowStore"/> 
 
--> 
 
<persistence class="com.opensymphony.workflow.spi.jdbc.JDBCWorkflowStore"> 
 

<property key="datasource" value="jdbc/DefaultDS"/> 
 
<property key="entry.sequence" 
 
                      value="select count(*) + 1 from os_wfentry"/> 
 
<property key="entry.table" value="OS_WFENTRY"/> 
 
<property key="entry.id" value="ID"/> 
 
<property key="entry.name" value="NAME"/> 
 
<property key="entry.state" value="STATE"/> 
 
<property key="step.sequence" 
 
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"/> 
 
<property key="history.table" value="OS_HISTORYSTEP"/> 
 
<property key="current.table" value="OS_CURRENTSTEP"/> 
 
<property key="historyPrev.table" value="OS_HISTORYSTEP_PREV"/> 
 
<property key="currentPrev.table" value="OS_CURRENTSTEP_PREV"/> 
 
<property key="step.id" value="ID"/> 
 
<property key="step.entryId" value="ENTRY_ID"/> 
 
<property key="step.stepId" value="STEP_ID"/> 
 
<property key="step.actionId" value="ACTION_ID"/> 
 
<property key="step.owner" value="OWNER"/> 
 
<property key="step.caller" value="CALLER"/> 
 
<property key="step.startDate" value="START_DATE"/> 
 
<property key="step.finishDate" value="FINISH_DATE"/> 
 
<property key="step.dueDate" value="DUE_DATE"/> 
 
<property key="step.status" value="STATUS"/> 
 
<property key="step.previousId" value="PREVIOUS_ID"/> 
 
</persistence> 
 

    <factory class="com.opensymphony.workflow.loader.XMLWorkflowFactory"> 
 
        <property key="resource" value="workflows.xml" /> 
 
    </factory> 
 
</osworkflow>



建立流程


建立一個命名為leave.xml的檔案,並將它放入WEB-INF/classes底下,檔名可自取,這個檔案就是記載流程的檔案。


<?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="開始"> 
 
      <results> 
 
        <unconditional-result old-status="Finished" status="Queued" step="1" /> 
 
      </results> 
 
    </action> 
 
  </initial-actions> 
 

  <steps> 
 
    <step id="1" name="填假單"> 
 
      <actions> 
 
        <action id="1" 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="2"  owner="User100" /> 
 
          </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>



接著在workflows.xml中加入如下的設定,即可讓系統於啟動後載入請假的流程,workflows.xml也放至WEB-INF/classes。



<workflows> 
 
    <workflow name="leave" type="resource" location="leave.xml"/> 
 
</workflows>



程式


這裡將建立兩個網頁分別給員工和主管使用,另外有兩個servlet及一個類別作為趨動流程。


    Leave.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 { 
 
/** 
 
* 送出假單 
 
*/ 
 
public long send(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); 
 
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(); 
 
} 
 

return workflowId; 
 
} 
 

/** 
 
* 准假假單 
 
* @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 (servlet) 
 

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.send(employee); 
 
resp.sendRedirect("allow.jsp?workflowId=" + workflowId); 
 
} 
 

}



    AllowAction.java (servlet)

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 AllowAction 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 { 
 
String workflowId = req.getParameter("workflowId"); 
 
String actionId = req.getParameter("actionId"); 
 
Leave leave = new Leave(); 
 
leave.allow(Long.parseLong(workflowId), Integer.parseInt(actionId)); 
 
} 
 

}

    leave.jsp


<!DOCTYPE HTML PUBLIC "-//W3C//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> 
 
</HEAD> 
 
<BODY> 
 
<P>員工請假</P> 
 

<form action="LeaveAction">



員工代號:

<input type="text" name="employee">  
 
        <input type="submit" value="送出"> 
 
</form> 
 

</BODY> 
 
</HTML>


    allow.jsp


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> 
 

<HTML> 
 
<HEAD> 
 
<%@ page language="java" contentType="text/html; charset=BIG5" 
 
pageEncoding="BIG5" %> 
 

<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(actionId) { 
 
document.myForm.actionId.value = actionId; 
 
document.myForm.submit(); 
 
} 
 
</Script> 
 
</HEAD> 
 
<BODY> 
 

<% 
 
String workflowId = request.getParameter("workflowId"); 
 
%> 
 

<P>主管批假單</P> 
 
<form action="AllowAction" name="myForm"> 
 
<input type="hidden" name="actionId" value=""> 
 
工作流編號: <input type="text" name="workflowId" value=<%= workflowId %>> 
 
<input type="button" value="准許" OnClick="DoAction(2)">  
 
<input type="button" value="駁回" OnClick="DoAction(3)"> 
 
</form> 
 

</BODY> 
 
</HTML>



測試


啟動Tomcat,並執行leave.jsp,按"送出"後,假單即送出,接著會出現allow.jsp的網頁供主管簽核,主管按"淮許"後,請假流程即完成,記得在執行過程中多觀察資料庫中資料的變化。








  • 大小: 13 KB
  • 大小: 17.2 KB
  • 大小: 19.3 KB