概 述
你可以從這裏找到常見問題的解答。
數據庫
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", "[email protected]");
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)
var d=new java.util.Date();
d.setTime(ACTIVITY_ACTIVATED_TIME.getTime()+300000);
d;
// Deadline limit is set to 1 hour after process is started
var d=new java.util.Date();
d.setTime(PROCESS_STARTED_TIME.getTime()+3600000);
d;
怎樣在 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">
<DataType>
<ExternalReference location="org.enhydra.shark.wrd.Participants"/>
</DataType>
</FormalParameter>
...
也許更好的途徑是定義 TypeDeclaration 元素做爲其類型。那樣的話你就可以隨處用到了(當建立程序的/子流程的 FormalParameters 時你不用定義適合的 DataType):
...
<TypeDeclaration Id="participants_type">
<ExternalReference location="org.enhydra.shark.wrd.Participants"/>
</TypeDeclaration>
...
定義 DataField 或 FormalParameter:
...
<DataField Id="participants" IsArray="FALSE">
<DataType>
<DeclaredType Id="participants_type"/>
</DataType>
</DataField>
...
<FormalParameter Id="participantGroup" Mode="INOUT">
<DataType>
<DeclaredType Id="participants_type"/>
</DataType>
</FormalParameter>
...
通過 ExternalReference 元素指定的類必須在 shark 類路徑中。
怎樣在 XPDL 中定義變量爲 'null' 的初始值
只需簡單將 DataField 的 InitialValue 元素寫成 "null":
<DataField Id="participants" IsArray="FALSE">
<DataType>
<DeclaredType Id="participants_type"/>
</DataType>
<InitialValue>null</InitialValue>
</DataField>
你可使用接口或抽象 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://blog.csdn.net/rosen)