概
述
?
???
???
你可以從這里找到常見問題的解答。
???
數據庫
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
編輯器
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>
怎樣指定腳本語言
?
???
??? 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.aygfsteel.com/rosen