概 述 ? ???
??? 你可以從這里找到常見問題的解答。
???
數據庫
Shark 怎樣與其他數據庫進行配置?
??? 結束安裝過程后,你將有已建好的 HipersonicSQL 數據庫。這還是比較有用的, Shark 也提供了你其他數據庫的選擇: DB2, PostgreSQL, MySQL,....
??? 首先你要停止任何可能正在運行的 Shark 實例( POJO swing 管理 /worklist 管理器,或 CORBA 服務器)。
??? 編輯 configure.properties 文件并為屬性設置參數:
??? db_loader_job
??? 目錄名包含了 Octopus 裝載工作,選項有: db2, hsql, informix, msql, mysql, oracle, postgresql, sybase
??? db_user
??? 數據庫驗證用戶名
??? db_passwd
??? 數據庫驗證密碼
??? db_ext_dirs
??? 包含 JDBC 驅動的 jar 文件目錄,如果你需要更多,一個 directory 將被指定 - 通過 ${path.separator} 連接它們
??? ${db_loader_job}_JdbcDriver
??? 要使用的 JDBC 驅動的類名
??? 這些項目都被填入了默認值。
??? ${db_loader_job}_Connection_Url
??? 完整的數據庫 URL
??? 這些項目也被填入了默認值。
??? 運行 configure.[bat|sh]
??? 注意
??? 當裝載新建的數據庫時, Octopus 將抱怨無法卸載索引和表,但這些警告應忽略掉。
怎樣清理 Shark 的數據庫?
??? 在測試過程中,你想清理數據庫并從頭開始。為了清理數據庫,你可運行 configure.[bat|sh] 文件。如果你不想等待多余的過濾, war 文件存檔的話 - 你應該運行 bin/recreateDB.[bat|sh] 文件。
??? 方法稍后只運行 Octopus 裝載工作來卸載以及建立表和索引。
怎樣調整數據庫訪問?
??? Shark 引擎是個組件包,部分利用 DODS 與數據庫交互。
??? 似乎有些控制 DODS 特性的參數很難理解。
??? DatabaseManager.DB.*.Connection.MaxPoolSize
??? 連接池能承受連接的最大數目。如果你知道程序不需要太多并發連接,它可以安全的減少數目。
??? DatabaseManager.DB.*.ObjectId.CacheSize
??? 作為組分配和保存在內存中的對象標識符數目。這些標識符被指派給新數據對象添加到數據庫。
??? DatabaseManager.defaults.cache.maxCacheSize
??? 根據對象存儲的最大數目限制的緩存大小。當緩存已滿,緩存中的對象按照 LRU (最近使用)原則被替換為新對象。
??? DatabaseManager.defaults.cache.maxSimpleCacheSize
??? DatabaseManager.defaults.cache.maxComplexCacheSize
??? 除了主要對象緩存,還有兩種查詢緩存可用(簡單和復雜)。查詢緩存也是 LRU 緩存。
??? DatabaseManager.defaults.maxExecuteTime
??? 每次運行查詢都比 maxExecuteTime 打印到( SQL 語句,執行時間和 maxExecuteTime )日志文件的時間長。這種方式可在你的程序或引擎內部發現很細微的可能問題。
??? DatabaseManager.DB.sharkdb.Connection.MaxPoolSize=300
??? DatabaseManager.DB.sharkdb.ObjectId.CacheSize=200
??? DatabaseManager.defaults.cache.maxCacheSize=100
??? DatabaseManager.defaults.cache.maxSimpleCacheSize=50
??? DatabaseManager.defaults.cache.maxComplexCacheSize=25
??? DatabaseManager.defaults.maxExecuteTime=200
??? 大量的緩存也不總是帶來高性能,這將導致內存的浪費和其他問題。
??? 如果你在相同數據庫上運行多個引擎實例(例如 集群),那就既不要 DODS 也不要 Shark 緩存。
客戶端接口
怎樣使用 Shark 庫
???? 客戶端程序通過 org.enhydra.shark.api.client 包中的一組接口來訪問 Shark 庫。首先客戶端程序應該配置庫或通過調用不帶參數的 configure() 方法(接著采用 Shark.conf 文件配置的 jar ),或通過指定文件名(做為 String 或 File 對象)或通過準備并調用 Properties 對象方法。配置完畢后 org.enhydra.shark.Shark.getInstance() 返回一個 SharkInterface 實例。從這點開始,客戶端程序開發者偏愛(或任務)知道程序怎樣使用庫,怎樣得到連接和執行指派或得到 AdminInterface 以及管理用戶、組、包, ...
??? 例子 1. 不是非常有用的 work-list 管理器
??? 例子的第一行,引擎使用 conf/Shark.conf 文件進行配置。當得到連接和成功連接后,引擎獲取 Resource 對象,來確定為用戶進行了多少指派(第 4 行)。
??? Shark.configure("conf/Shark.conf");
??? SharkConnection sConn = Shark.getInstance().getConneciton();
??? sConn.connect(userId, passwd, engineName, scope);
??? if (0 < sConn.getResourceObject().how_many_work_item())
??????? System.err.println("Oh, let these tasks wait until tomorrow!");
??? }
??? System.out.println("Job done!");
??? 例子 2. 用戶組管理
??? 該范例不能運行。如果你把 Shark 配置為使用 LDAP user-group 組件,但是基于組件的數據庫開始時確是空的,所以要做任何實際的工作你都需要定義至少一個組和用戶。
??? Shark.configure();
??? UserGroupAdministration ugAdmin =
????? Shark.getInstance().getAdminInterface().getUserGroupAdministration()
? ?? ugAdmin.crateGroup("developers","sweat-shop");
??? ugAdmin.createUser("developers", "user", "secret", "Jane Doe", "some@email.address");
??? System.out.println("Group and user created!");
? ?? 例子 3. 裝載包到 Shark 庫
??? 包的 XPDL 文件位置與包知識庫的根路徑有關。在你執行該操作之前,通過在客戶端對象調用 getDefinedPackagesPath() 方法你將得到所有的包相關路徑。首先根據包知識庫的根路徑,找到你需要包的 XPDL 文件位置,接著要有 PackageAdministation 實例。
??? String xpdlName = "test.xpdl";
??? Properties props = new Properties();
??? props.setProperty("enginename","testSharkInstance");
??? props.setProperty("EXTERNAL_PACKAGES_REPOSITORY","c:/Shark/repository/xpdls");
??? Shark.configure(props);
??? String pkgId = Shark.getInstance().getRepositoryManager().getPackageId(xpdlName);
??? PackageAdministration pa = Shark.getInstance().getAdminInterface().getPackageAdministration();
??? if (!pa.isPackageOpened(pkgId)) {
????? pa.openPackage(xpdlName);
??? System.out.println("Package "+ xpdlName +" is loaded");
??? 例子 4. 構建和開始流程
??? 當加載 XPDL 到 shark 后,再構建它,填入初始化變量值,啟動基于 XPDL 定義的流程。
??? String pkgId="test";
??? String pDefId1="basic";
??? String pDefId2="complex"; ??? SharkConnection sConn=Shark.getInstance().getConnection(); ??? sConn.connect("user","secret","",""); ??? WfProcess proc1=sConn.createProcess(pkgId,pDefId1);
??? WfProcess proc2=sConn.createProcess(pkgId,pDefId2); ??? proc1.set_process_context("test_var","This is String variable defined in XPDL for the process basic");
??? proc2.set_process_context("counter",new Long(55)); ??? proc1.start();
??? proc2.start();
??? 例子 5. 設置變量
??? 成功連接上 Shark 后,獲得指派列表,再作些有用的事,比如設置變量和完成該活動。
?? /*
?? SharkConnection sConn;
?? String activityId;
?? String vName;
?? String vValue;
??? */
?? WfAssignment a = null;
?? WfAssignment[] ar = sConn.getResourceObject().get_sequence_work_item(0);
?? for (int i = 0; i < ar.length; ++i) {
????? if (activityId.equals(ar[i].activity().key())) {
???????? a = ar[i];
???????? break;
????? }
?? }
?? if (null == a)
????? throw new BaseException("Activity:"
????????????????????????????? + activityId
????????????????????????????? +" not found in "
????????????????????????????? + sConn.getResourceObject().resource_key()
????????????????????????????? +"'s worklist");
?? if (!a.get_accepted_status())
????? throw new BaseException("I don't own activity "+ activityId);
?? Map _m = new HashMap();
?? WfActivity activity = a.activity();
?? Object c = activity.process_context().get(vName);
?? if (c instanceof Long) {
????? c = new Long(vValue);
?? } else {
????? c = vValue;
?? _m.put(vName, c);
?? activity.set_result(_m);
?? activity.complete();
??
??? 例子 6. 獲得基于標準的流程管理器
??? 該范例展示了怎樣獲得基于標準的流程管理器。范例試圖得到包 Id 為 "test" 并且狀態是 enabled 的所有流程管理器。
?? ExecutionAdministration eAdmin=Shark.getInstance().getAdminInterface().getExecutionAdministration();
?? eAdmin.connect("user","secret","",""); ?? WfProcessMgrIterator pmi=eAdmin.et_iterator_processmgr();
?? query="packageId.equals(\"test\") && enabled.booleanValue()";
?? pmi.set_query_expression(query);
?? WfProcessMgr[] procs=pmi.get_next_n_sequence(0);
??? 例子 7. 獲得基于標準的流程
??? 該范例展示了怎樣獲得由基于標準的流程管理器構建的流程。范例試圖得到所有狀態為 "open.running" ,并且是十分種之前啟動,有 3 個以上的激活活動,有叫做 "myvariable" 且值為 "test" 的 String 類型變量的流程。
?? WfProcessMgr mgr;
?? */ ?? WfProcessIterator wpi=mgr.get_iterator_process ();
?? query="state.equals(\"open.running\") && startTime.longValue()>(java.lang.System.currentTimeMillis()-10*60*1000) && activeActivitiesNo.longValue()>3 && context_myvariable.equals(\"test\")";
?? wpi.set_query_expression(query);
?? WfProcess[] procs=wpi.get_next_n_sequence(0);
??? 例子 8. 使用外部事務 ? ???
??? Shark API 的每個方法這樣調用分離事務:引擎內部構建,使用,任意提交,最終釋放事務。這意味著每個使用 Shark 的簡單代碼將不知不覺使用很多事務。 ? ???
??? 有時,外部事務要做些不同的事情,于是 SharkTransaction 被引入進來了。一個程序(的開發者)會因為多種因素選擇使用外部事務,比如使用相同數據庫保存程序( work-flow 無關)數據,這是為避免經常構建 / 丟棄事務, ...? ???
? ?? 當然,這種方法也會有代價:你必須遵從于使用規則。通過調用 Shark.getInstance().createTransaction(); 事務被構建,在你釋放一個事務之前,程序必須調用 Shark.getInstance().unlockProcesses(st); 通知 Shark 進行內部記帳。如果有任何錯誤,你必須捕捉 Throwable (異常)再調用 Shark.getInstance().emptyCaches(st); 。是的,你甚至應該為捕獲錯誤而準備好,另外你將面對未知狀態下脫離引擎。
???? 這是利用單一事務進行變量設置的例子。 ? ???
????? /*
????? SharkConnection sConn;
????? String activityId;
????? String vName;
????? String vValue;
?????? */
????? SharkTransaction st = Shark.getInstance().createTransaction();
????? try {
???????? WfAssignment a = null;
???????? WfAssignment[] ar = sConn
??????????? .getResourceObject(st)
??????????? .get_sequence_work_item(st, 0);
???????? for (int i = 0; i < ar.length; ++i) {
??????????? if (activityId.equals(ar[i].activity(st).key(st))) {
?????????????? a = ar[i];
?????????????? break;
??????????? }
???????? }
???????? if (null == a)
??????????? throw new BaseException("Activity:"
?????????????????????????????????????? + activityId
?????????????????????????????????????? +" not found in "
?????????????????????????????????????? + sConn.getResourceObject(st).resource_key(st)
?????????????????????????????????????? +"'s worklist");
???????? if (!a.get_accepted_status(st))
??????????? throw new BaseException("I don't own activity "+ activityId);
???????? Map _m = new HashMap();
???????? WfActivity activity = a.activity(st);
???? ????Object c = activity.process_context(st).get(vName);
???????? if (c instanceof Long) {
??????????? c = new Long(vValue);
???????? } else {
??????????? c = vValue;
???????? _m.put(vName, c);
???????? activity.set_result(st, _m);
???????? activity.complete(st);
???????? st.commit();
????? } catch (Throwable t) {
???????? Shark.getInstance().emptyCaches(st);
???????? st.rollback();
???????? if (t instanceof RootException)
??????????? throw (RootException)t;
???????? else
??????????? throw new RootException(t);
????? } finally {
???????? try { Shark.getInstance().unlockProcesses(st);} catch (Exception _){}
???????? st.release();
XPDL 流程定義 ? ???
??? (通過我們的 XPDL 編輯器 JaWE 會使構建 XPDL 變得簡單。)
??? 怎樣為活動定義 deadline 表達式?
???? 在 shark deadline 表達式中連同所有流程變量,你能使用特殊變量。這些變量的 Java 類型是 java.util.Date ,以下是描述: ? ???
??? PROCESS_STARTED_TIME - 流程開始的時間 ? ???
??? ACTIVITY_ACTIVATED_TIME - 當流程流到活動以及為活動構建指派的時間。 ? ???
??? ACTIVITY_ACCEPTED_TIME - 第一次為活動指派的接收時間。
??? 注意 ? ???
??? 如果活動在接收后被拒絕,或根本沒有接收, ACTIVITY_ACCEPTED_TIME 將會設置成最大值。
???? 在構建 deadline 表達式時有些規則:
??? Deadline 表達式就是 java.util.Date
??? 如果 shark 設置為沒有重評估 deadline ,而只是最初評估 deadline 時間期限, ACTIVITY_ACCEPTED_TIME 不會被用在表達式中,因為它將在以后包含最大時間值。
??? 那些不是流程變量(來自于 XPDL 的 DataField 或 FormalParameter 實體),和先前列出的其中之一有相同 Id 。
??? 一點 deadline 表達式的例子: ? ???
// Deadline limit is set to 15 secunds after accepting activity
var d=new java.util.Date();
d.setTime(ACTIVITY_ACCEPTED_TIME.getTime()+15000);
d;
// Deadline limit is set to 5 minutes after activity is started (activated)
d.setTime(ACTIVITY_ACTIVATED_TIME.getTime()+300000);
// Deadline limit is set to 1 hour after process is started
d.setTime(PROCESS_STARTED_TIME.getTime()+3600000);
怎樣在 shark 管理程序中定義外部屬性來更新 / 查看活動變量
??? 為了更新 shark 管理程序中的活動變量(由 XPDL 定義), XPDL 活動定義必須包含預先擴充的屬性。 ? ???
??? 假如 XPDL 流程定義包含叫做 "x" 的變量( XPDL DataField 標記),和叫做 "input_var" 的變量( XPDL FormalParameter 類型)。 ? ???
??? 如果在執行活動時你想讓管理用戶僅僅查看那些變量,你應該定義如下活動擴展屬性: ? ???
<ExtendedAttribute Name="VariableToProcess_VIEW" Value="x"/>
<ExtendedAttribute Name="VariableToProcess_VIEW" Value="input_var"/>
??? 如果你想要用戶更新同樣的變量,你應該定義如下活動擴展屬性:
<ExtendedAttribute Name="VariableToProcess_UPDATE" Value="x"/>
<ExtendedAttribute Name="VariableToProcess_UPDATE" Value="input_var"/>
在 Shark 中怎樣讓 XPDL 使用自定義 Java 類做為變量 ? ???
??? 要做到這些,你應該定義變量作為 XPDL 的外部引用,并把你想要用的完整 Java 類名做為它的屬性。比如,像這樣: ? ???
...
<DataField Id="participants" IsArray="FALSE">
?? <DataType>
????? <ExternalReference location="org.enhydra.shark.wrd.Participants"/>
?? </DataType>
</DataField>
<FormalParameter Id="participantGroup" Mode="INOUT">
</FormalParameter>
??? 也許更好的途徑是定義 TypeDeclaration 元素做為其類型。那樣的話你就可以隨處用到了(當建立程序的 / 子流程的 FormalParameters 時你不用定義適合的 DataType ): ? ???
<TypeDeclaration Id="participants_type">
?? <ExternalReference location="org.enhydra.shark.wrd.Participants"/>
</TypeDeclaration>
??? 定義 DataField 或 FormalParameter : ? ???
????? <DeclaredType Id="participants_type"/>
??? 通過 ExternalReference 元素指定的類必須在 shark 類路徑中。
怎樣在 XPDL 中定義變量為 'null' 的初始值 ? ???
??? 只需簡單將 DataField 的 InitialValue 元素寫成 "null" :
??? <DataField Id="participants" IsArray="FALSE">
? ???? <DeclaredType Id="participants_type"/>
?? <InitialValue>null</InitialValue>
?? 你可使用接口或抽象 java 類做為工作流變量。這些變量的具體實現可由一些 tool agent 構建。 ?
怎樣指定腳本語言 ? ???
??? Shark 目前支持三種腳本解釋器: JavaScript , BeanShell 和 Python (最后一個未完全測試)。要告訴 shark 哪種腳本語言被用于書寫條件式(比如在事務條件中),你應該指定包的 script 元素: ? ???
# if you want to use java-like syntax (interpreted by BeanShell), specify: <Script Type="text/java"/>
# if you want to use java script syntax, specify: <Script Type="text/javascript"/>
# if you want to use python syntax, specify: <Script Type="text/pythonscript"/>
??? 如果你沒有指定腳本或指定的值不被 shark 支持, Shark 將會抱怨。
怎樣利用 XPDL 為特定的 ToolAgent 直接映射程序定義(不需要在運行期為程序映射) ? ???
? ?? 如果你想直接在 XPDL 中指定 ToolAgent , Tool 活動將執行該 ToolAgent ,所以你應該為 XPDL 程序定義設置一些擴展屬性。 ? ???
?? ? 主要的擴展屬性應該在每個程序定義中定義,趨向于映射給名叫 "ToolAgentClass" 的 ToolAgent ,并且它的值應該是被執行的 tool agent 類全名,例如: ? ???
??? <ExtendedAttribute Name="ToolAgentClass" Value="org.enhydra.shark.toolagent.JavaScriptToolAgent"/>
??? 該屬性通過 shark 的 tool agent 定義工具閱讀,并且它執行基于該屬性值的特定 ToolAgent 。
??? 其他外部屬性被指定來實現 tool agent ,并通過它們讀取。比如 JavaScript 和 BeanShell tool agent 指定了名為 "Script" 的外部屬性,而且內容是通過 tool agent 在運行期執行腳本獲得的。這種情況下,你就是在用 XPDL 編程了,例如: ???
??? <ExtendedAttribute Name="Script" Value="java.lang.System.out.println("I'm going to perform operation c="+a+"*"+b); c=a*b; java.lang.System.out.println("The result is c="+c);"/>
??? 該腳本運行了變量 "a" 和 "b" 的乘法運算,并把結果保存在 "c" 中(那些變量都是 XPDL 程序定義的形參)。?請注意!引用、轉貼本文應注明原譯者:Rosen Jiang 以及出處:http://www.tkk7.com/rosen
Powered by: BlogJava Copyright © Rosen