OSWorkflow的第一個程序


OSWorkflow的第一支程式
(史帝芬, 2005/6/4, [email protected])
自從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">&nbsp;
            <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)">&nbsp;
    <input type="button" value="駁回" OnClick="DoAction(3)">
    </form>
    
    </BODY>
    </HTML>
    
  • 測試
    啟動Tomcat,並執行leave.jsp,按"送出"後,假單即送出,接著會出現allow.jsp的網頁供主管簽核,主管按"淮許"後,請假流程即完成,記得在執行過程中多觀察資料庫中資料的變化。
        請假

        准假

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章