如何使用Shark
翻译人:林勇 QQ:313340285
Email:[email protected] MSN:[email protected]
Skype:showsscel
Shark介绍及配置 -- Enhydra Shark
2007 年 3 月 16 日
版本:1.0
本文仅代表个人对Shark的理解,如有理解错误或不准确的地方,敬请大家指出,我将急时修证。迎大家共同交流、相互学习。 |
3 3 3 4 5 5 10 10 11 11 12 13 13
|
数据库………………………………………………………………………………………………
如何配置shark使用其它数据库?…………………………………………………………
如何清除Shark数据库?……………………………………………………………………
如何调整数据库访问?………………………………………………………………………
Shark客户端接口……………………………………………………………………….. …………
如何使用shark库………………………………………………………………………………
XPDL流程定义…………………………………………………………………………………….
如何写活动的最终期限表达式………………………………………………………………..
如何在shark的管理应用中写为更新/浏览活动变量的扩展属性…………………………..
如何在shark中写使用自定义Java类变量的XPDL………………………………………..
如何在XPDL中定义变量初始化为“null” ………………………………………………
如何指定脚本语言……………………………………………………………………………
如何使用XPDL直接映射应用程序定义到具体的工作代理(运行时不需要应用程序映射)
摘要
这里你可以找到常见问题的答案。
配置程序结束后将有一个HipersonicSQL数据被创建。这是完全可用的,Shark提供一个选项使用其它数据库:DB2,PostgreSQL,MySQL,。。。。。
·首先你需要停止任何可能运行(POJO swing管理应用/任务管理者,或者CORBA服务器)的Shark实例。
·编辑configure.properties文件设置下列值:
db_loader_job 包含Octoputs装载器作业的目录名称,选项是:db2,hsql,Informix,msql,mysql,oracle,postgresql,sybase;
db_user 数据库认证用户名;
db_passwd 数据库认证用户密码;
db_ext_dirs 包含JDBC驱动程序包的目录,如果需要定义多于一个的目录- 用${path.separator}连接它们;
${db_loader_job}_JdbcDriver 你想使用的JDBC驱动器名称,这些条目已经填充了默认值;
${db_loader_job}_Connection_Url 完整的数据库URL,这些条目已经填充了默认值;
·运行configure.[bat|sh]
注意:装载新创建的数据库时,Octopus将抱怨不能删除索引和表,但是这些警告被忽略。
在测试流程中将开始你想清除的数据并且从零开始,清除数据库你可以运行主configure.[bat|sh]文件。如果你不想等待不必要的过滤,war文档 – 你运行bin/recreateDB.[bat|sh]。
后面的方法只运行Octopus装载作业删除和创建表和索引。
Shark引擎是组件的一部份,它们中的一些是用DODS与数据库通信[http://dods.objectweb.org/]。
也许知道一些控制DODS行为的参数是派得上用场的。
DatabaseManager.DB.*.Connection.MaxPoolSize
连接池控制的连接最大数。如果你知道应用不需要这么多同时连接,在这个连接数量下是安全的。
DatabaseManager.DB.*.ObjectId.CacheSize
在内存中被分配为一个组和句柄的对象标识数量。
DatabaseManager.defaults.cache.maxCacheSize
限制能够被存储的对象最大数的缓存的大小。缓存大小是完整的,缓存中的对象通过LRU运算法则用新的对象替换。
DatabaseManager.defaults.cache.maxSimpleCacheSize and DatabaseManager.defaults.cache.maxComplexCacheSize
与主对象缓存相比,有可能使用两种查询缓存(简单的和复合型)。这些查询缓存也是LRU运算法则缓存。
DatabaseManager.defaults.maxExecuteTime
比最大查询时间更长的每一个查询被打印(SQL声明,执行时间和最大执行时间)到日志文件中。通过这种方式你可以发现在应用或引擎内部可能出现的问题。
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的缓存。
客户端应用通过在org.enhydra.shark.api.client包中的接口设置使用Shark库。首先应用通过调用没有参数(从jar文件中的Shark.conf配置文件中配置Shark)的configure()方法配置任何库,或者调用指定文件名的或准备一个Properties对象的调用方法。配置后org.enhydr.shark.Shark.getInstance()返回一个SharkInterface实例。从这个入手,应用开发者参考(或分配任务)如何使用shark库,或者获取一个连接和执行任务分配或获取一个AdminInterface管理用户,组,包等等。
例1.不是非常有用的任务列表管理者
例子的第一行使用conf/Shark.conf文件配置引擎。然后获取一个连接并且成功连接到Shark.查询当前用户有多少资源对象分配(在第四行)。
Shark.configure("conf/Shark.conf");
SharkConnection sConn = Shark.getInstance().getSharkConnection();
sConn.connect("qq", "lele", "shark", "");
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为用户组管理组件该例子是不能运行的,但是基于数据库组件开始为空,至少定义一个组和用户对于任何操作是有用的。
Shark.configure();
UserGroupAdministration ugAdmin = Shark.getInstance()
.getAdminInterface()
.getUserGroupAdministration();
ugAdmin.createGroup("developers", "sweat-shop");
ugAdmin.createUser("developers",
"user",
"secret",
"Jane",
"Doe",
System.out.println("Group and user created!");
例3.装载包到Shark的库
包的XPDL文件位置是XPDL包仓库根的相对路径。执行操作之前,可能想在客户端对象中调用getDefinedPackagesPath()方法取所有包相对路径。首先你需要相对于XPDL包仓库的包的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().getSharkConnection();
sConn.connect("user", "secret", "", "");
WfProcess proc1 = sConn.createProcess(pkgId, pDefId1);
WfProcess proc2 = sConn.createProcess(pkgId, pDefId2);
Map m1 = new HashMap();
m1.put("test_var",
"This is String variable defined in XPDL for the process basic");
proc1.set_process_context(m1);
Map m2 = new HashMap();
m2.put("counter", new Long(55));
proc2.set_process_context(m2);
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”并且状态为激活的所有流程管理器。
ExecutionAdministration eAdmin = Shark.getInstance()
.getAdminInterface()
.getExecutionAdministration();
eAdmin.connect("user", "secret", "", "");
WfProcessMgrIterator pmi = eAdmin.get_iterator_processmgr();
String query = "packageId.equals(/"test/") && enabled.booleanValue()";
pmi.set_query_expression(query);
WfProcessMgr[] procs = pmi.get_next_n_sequence(0);
例7.基于一些规则获取流程
这个例子展示如何基于一些规则通过一些流程管理器获取流程。它试着获取状态为“open.running”,并且在最近10分钟中启动,并且多于三个活动行为,并且“myvariable”字符串变量的值为“test”的所有流程。
/*
WfProcessMgr mgr;
*/
WfProcessIterator wpi = mgr.get_iterator_process();
String 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被引入。一个应用可以选择使用外部事务为多个理由,包括使用同一数据库存储应用数据,消除频繁创建/释放事务,。。。。
当然,这个方法是有代价的:你必须服从使用角色。事务创建调用Shark.getInstance().createTransaction()方法,只不过释放之前你的应用必须调用Shark.getInstance().unlockProcesses(st)方法通知Shark做内部登记。如果发生任何错误你必须捕获异常并调用Shark.getInstance().emptyCaches(st)清除缓存。是的,你读取知觉的错误信息必须捕获它,否则你将在不明确的状态下退出shark引擎。
这里是可用于设置修改使用单事务的例子。
/*
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[http://jawe.objectweb.org]很容易创建XPDL。)
Shark中的最终期限表达式连同所有流程变量一起,你可以指定变量。Java变量类型是java.util.Date,这里是它们的描述:
·PROCESS_STARTED_TIME – 流程启动的时间;
·ACTIVITY_ACTIVATED_TIME – 流程到达和任务分配活动创建的时间;
·ACTIVITY_ACCEPTED_TIME – 第一个任务分配活动创建的时间;
注意:如果活动在接受之后被拒绝,或者没有被任何人接受, ACTIVITY_ACCEPTED_TIME将来被设置为一些最大值。
这里是一些创建最终期限表达式的规则:
·最终期限表达式用java.util.Date对象返回值;
·如果shark没有设置重新评估最终期限,而是初化时评估最终期限限制时间,因为将来它包含一些最大时间,所以ACTIVITY_ACCEPTED_TIME不应该用于表达式中。
·在最终期限表达式中不应该有相同Id的流程变量(来自于XPDL中的工作流相关数据或形式参数)。
这里是最终期限表达式的几个例子:
// 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管理应用中为了更新活动变量,XPDL活动定义必须包含一些预告确定的扩展属性。
假如XPDL流程定义包含变量(XPDL工作流相关数据标签)“x”和变量(XPDL形式参数类型)“input_var”。
如果执行活动时你想管理用户只是能浏览这些变量,你将定义下列的活动扩展属性:
如果你想用户更新相同的变量,你将定义下列的活动扩展属性:
你将定义变量为XPDL外部参考能够做到,设置你想使用的Java类的全名为位置属性。例如:它应该看起来像下面这样:
...
...
...
...
也许最好的方法是定义将使用类型的类型声明元素。你能够在任何地方使用(创建应用/子流程的形式参数时不需要定义适当数据类型):
...
...
然后定义如何数据类型或形式参数:
...
...
...
通过外部参数元素指定的类必须在shark的类路径中存在。
你简单写入“null“为初始化工作流相关数据元素:
你能够使用接口或抽象java类为工作流变量。这些类的具体实现能够被工具代理创建。
Shark现在支持三种脚本解释程序:JavaScript,BeanShell,Python(最后一种没有完全测试过)。告诉shark那个脚本语言被使用在条件表达式,你将指定包的脚本元素:
# if you want to use java-like syntax (interpreted by BeanShell), specify:
# if you want to use java script syntax, specify:
# if you want to use python syntax, specify:
如果你没有指定脚本或指定了shark不支持的脚本Shark将发出警告。
如果你想在XPDL中直接指定被工具活动执行的具体工具代理,你将为XPDL应用程序定义一些扩展属性。
注意映射到工具代理名“ToolAgentClass”的每个应用程序定义的主要扩展属性,它的值是描述工具代理执行的类的全名,例如:
这个属性被shark默认的工具代理读取,shark执行基于这个属性值指定的工具代理。
其它的扩展属性是指定被工具代理的实现读取的参数,例如,JavaScript和BeanShell工具代理指定扩展属性名“Script”,该属性的值是运行时工具代理执行的脚本内容。既然这样,你事实上使用XPDL为程序服务。例如:
这个脚本执行变量“a”和“b”相乘,结果保存到“c”(这些变量是XPDL应用程序定义的形式参数)。