BPM 應用系統開發案例實戰4


表 6. 使用 JSP 實現的系統界面

名稱

訪問路徑

描述

approver.jsp

/approver/approver.jsp

頁面啟動時向後台 LoadApproveData 請求並展示需要審核的發票數據,並向 ApproverServlet 發送審核請求

basic_index.jsp

/indexer/basic_index.jsp

發票錄入員所示用的發票數據錄入頁面,向 DisposeIndexServlet 發送請求數據,其包含兩個標籤頁,區分待審核數據和基本的流程數據

index_list.jsp

/indexer/index_list.jsp

系統起始頁面,用於展示當前所有活動的流程實例的列表,通過向 LoadProcessListData 發送請求獲取數據

調用 WebAPI 必須包含的兩個主要的 Jar 包,其中 teamworks-client-sample.jar 是使用 WebAPI 的輔助類,可以在 IBM BPM 的安裝目錄下找到,其中的 lib 目錄下包含了使用該 Jar 包所依賴的其他的 Jar 包。webapi.jar 是連接 IBM BPM 的功能包,可以在服務端安裝目錄下直接找到。將所需包導入到工程的 Class Path 下。

新建一個普通 Java 類,命名為 WebAPIUtil,該類利用 teamworks-client-sample.jar 所提供的功能,產生 WebAPI 的實例,詳細代碼可查看示常式序程序中的 WebAPIUtil.java,下面是關鍵代碼:


清單 1. 創建 WebAPI 實例代碼片段

                

 

WebAPIFactory factory = WebAPIFactory.newInstance(properties);

// Create a new WebAPI client stub

factory.setProperty(Stub.USERNAME_PROPERTY, username);

factory.setProperty(Stub.PASSWORD_PROPERTY, password);

webAPI = factory.newWebAPI();


 

 

上面這段代碼展示了通過 WebAPIFactory 產生 WebAPI 連接實例的過程,其中 username、password 用於連接 IBM BPM 的服務端,必須是合法的用戶名 / 密碼對,properties 對象通過 properties 配置文件產生,可參考示常式序中的 WebAPIFactory.properties 文件,內容如下:


清單 2. WebAPIFactory.properties 配置文件內容片段

                

 

Wjavax.xml.rpc.service.endpoint.address=

http://[ibm-bpm-host]:[port]/webapi/services/WebAPIService

javax.xml.rpc.session.maintain=true

com.lombardisoftware.includeNullArrayElements=true


 

 

其中第一條配置信息包含了要訪問的 WSDL 文件的地址,[ibm-bpm-host]:[port] 分別是 IBM BPM 的伺服器地址和埠號。

新建一個 Servlet,取名為 LoadProcessListData,該程序創建一個查詢(Search),查詢出當前伺服器所有活動的流程實例,詳細代碼可查看示常式序中的 LoadProcessListData.java,關鍵代碼如下:


清單 3. LoadProcessListData.java 代碼片段

                

 

WwebAPI = WebAPIUtil.getWebAPIConnection(username, password,webAPIProperty);

// execute query to get the process instance list

SearchResultRow[] rrs = getActiveInstanceList();

// generate XML data

String xmloutput = getXMLDataFromSearch(rrs);


 

 

其中第一行代碼展示了通過先前創建的輔助工具類獲取 WebAPI 的實例,第三個參數為配置文件所在的路徑。第二行代碼通過調用一個方法獲取查詢的結果了數組,最後通過該數組生成需要返回的 XML 字元串,其中獲取查詢結果的代碼如下:


清單 4. 獲取查詢結果的代碼片段

                

 

Search se = new Search();

se.setOrganizedByType(“ProcessInstance”);

SearchResults sr = null;

 

// set search column for the search and search result

SearchColumn searchColumn1 = new SearchColumn();

searchColumn1.setType(“ProcessInstance”);

searchColumn1.setName(SearchableProcessInstanceColumn._Id);

SearchColumn searchColumn2 = new SearchColumn();

searchColumn2.setType(“ProcessInstance”);

searchColumn2.setName(SearchableProcessInstanceColumn._Name);

 

// set the condition

SearchColumn searchColumn3 = new SearchColumn();

searchColumn3.setType(“ProcessInstance”);

searchColumn3.setName(SearchableProcessInstanceColumn._Status);

SearchCondition searchCondition1 = new SearchCondition();

searchCondition1.setColumn(searchColumn3);

searchCondition1.setOperator(“EQUALS”);

searchCondition1.setValue(“Active”);

 

// create data

SearchColumn[] scs = new SearchColumn[2];

scs[0] = searchColumn1;

scs[1] = searchColumn2;

SearchCondition[] sCond = new SearchCondition[1];

sCond[0] = searchCondition1;

 

// do the search

se.setColumns(scs);

se.setConditions(sCond);

try {

sr = webAPI.executeSearch(se, null, null);

} catch (RemoteException e) {

e.printStackTrace();

}

return sr.getRows();


 

 

此段代碼先創建一個 Search 對象,然後將結果的組織類型設置為根據”ProcessInstance”的方式,及以 Process 實例為基本單位獲取結果,5 至 10 行創建需要展示的結果的列,12 至 18 行創建需要查詢的條件,20 至 24 行設置查詢數據,最後調用 WebAPI 的方法執行查詢並返回結果。

當然,調用 Search 的方式除了上面介紹的通過代碼硬編碼的方式以外,還可以通過 IBM BPM 的 Portal 創建 Saved Search,然後通過 WebAPI 直接調用,類似於調用資料庫中的存儲過程。

此時通過界面即可查看當前的活動的實例列表,界面詳細代碼可查看示常式序中 index_list.jsp 及 process_instance_list.js 文件。

新建一個 Servlet,命名為 DisposeIndexServlet,該 Servlet 會接受頁面參數,將參數通過”COCE_GIW_ALL_Index”活動傳入到流程中,並將流程從當前活動推動到下一個指定的活動節點上,詳細代碼可查看示常式序中的 DisposeIndexServlet.java,下面是關鍵代碼:


清單 5. DisposeIndexServlet.java 代碼片段

                

 

int variableLength = 5; // variable length need to

// initialize the varaibles

Variable[] vars = new Variable[variableLength];

for(int i=0; i<vars.length; i++){

vars[i] = new Variable();

}

vars[0].setName(“maxNumberApprovers”);

vars[0].setValue(numApprs);

try {

vars[1] = makeApproverName(approvers);

} catch (ParserConfigurationException e) {

e.printStackTrace();

} catch (SAXException e) {

e.printStackTrace();

}

vars[2].setName(“duplicateCheck”);

vars[2].setValue(duplicateCheck);

……

vars[3] = makeContentList(contents);

 

// dispose the complex value

ComplexValue cv = (ComplexValue)vars[3].getValue();

MessageElement arrayOfStr = cv.get_any()[0].getRealElement();

if(null != arrayOfString){

List<MessageElement> elementList = arrayOfStr.getChildren();

for(MessageElement strEle : stringElementList){

Text e = (Text) strEle.getChildren().get(0);

e.setValue(mailContent);

}

}

vars[4] = makeInvoiceData(data);


 

 

如上所示,程序首先創建 Variable 類型的數組,程序通過該數組給 Process 實例傳遞參數,對於簡單參數,只需要調用 Variable 對象的 setName 和 setValue 為設置名稱和對應的值,名稱必須和活動中的參數名稱相同。代碼中 vars[1]、vars[3] 和 vars[4] 比較特殊,因為他們都是複雜類型的數據,類似於 C/C++ 中的結構體,需要通過反序列化的方式,其中 vars[1] 對應了流程定義中的參數 approverNames,它是一個 String 的列表類型,但是不同於 Java 的 String[] 或是 List<String> 及其子類型 , 後面會有詳細的介紹,vars[3] 對應了 BPD 中的 mailContents 參數,也是 String 列表類型,vars[4] 對應了 BPD 中的 InvoiceDataModel 類型,同樣是複雜類型的數據結構,下面以 InvoiceDataModel 為例,介紹一下 makeInvoiceData 方法中的序列化代碼,如下:


清單 6. 序列化代碼片段

                

 

Variable v = null;

StringBuffer outputXml =

new StringBuffer(“<InvoiceDataModel xmlns=\”http://www.w3.org/2001/XMLSchema\”>”);

outputXml.append(“<Source>” + data.source + “</Source>>”);

outputXml.append(“<UserID>” + data.userid + “</UserID>”);

outputXml.append(“<Timestamp>” + data.Timestamp + “</Timestamp>”);

outputXml.append(“<D_DocStatus>” + data.d_DocStatus + “</D_DocStatus>”);

outputXml.append(“<ORIGIN_ITEM_ID>” + data.origin_item_id + “</ORIGIN_ITEM_ID>”);

outputXml.append(“<OLD_CREATETS>” + data.old_creates + “</OLD_CREATETS>”);

outputXml.append(“</InvoiceDataModel>”);

// create variable

v = new Variable(“invoiceData”, ClientUtilities.toComplexValue(outputXml.toString()));

return v;


 

 

在構建流程定義的過程中,我們創建了複雜的數據類型 InvoiceDataModel,圖 26 展示了該數據類型的 Schema 定義,上面的代碼即根據該 Schame 的定義構建複雜數據類型的結構,最後通過 ClientUtilities 將 XML 轉換成一個

以下文章點擊率最高

Loading…

     

如果這文章對你有幫助,請掃左上角微信支付-支付寶,給於打賞,以助博客運營