摘要:
你可以在这里找到被问的频率最高的问题的答案
数据库
如何配置shark工作在其他的数据库上?
当安装进程结束后,你的默认HipersonicSQL数据库将被创建,在他被安静地使用时,shark还提供了许多其他数据库可供选择:DB2、PostgreSQL、MYSQL……
l首先,你需要停止所有正在运行的shark实例。
l其次,编辑configure.properties文件设置如下属性:
ü db_loader_job:包含loader job路径的名称属性有:db2、hsql、infomix、mssql、mysql、oracle、postgresql、sybase
ü db_user: 数据库用户名称
ü db_passwd: 数据库密码
ü db_ext_dirs:包含jdbc驱动程序的目录
ü ${db_loader_job}_JdbcDriver:你想要使用的jdbc驱动程序的名称
ü ${db_loader_job}_Connection_Url:数据库连接字符串
l运行configure.bat/sh
如何清空shark数据库?
在测试流程时,你需要清空数据库使程序从头开始,为了清空数据库,你应先运行configure.bat/sh文件,如果你不想等待不必要的过滤、war归档,你可以运行bin/recreateDB.[bat|sh]
如何调整数据库存取?
Shark引擎是一个组件群,其中一些通过使用DODS和数据库交互。从这里 你可以很便利地知道一些DODS行为控制的参数用法。
DatabaseManager.DB.*.Connection.MaxPoolSize
数据库连接池能够保持的数据库连接的最大数。如果你知道你的应用程序不需要如此多的并发连接量,你可以安全地减少他,而不会影响应用程序
DatabaseManager.DB.*.ObjectId.CacheSize
对象标识符的数量,他们作为组被分派,并且保存在内存中,这些标识符被分配为新的数据对象,并且插入到数据库中。
DatabaseManager.defaults.cache.maxCacheSize
Cache的数量被对象的最大数所限制,当这个cache满了以后,里面的对象将以LRU算法被新的对象替换。
DatabaseManager.defaults.cache.maxSimpleCacheSize and DatabaseManager. defaults.cache.maxComplexCacheSize
和主对象缓存相比,有一个使用两个查询缓存的可能性(简单的和复杂的)。这些查询缓存也是使用lru算法的缓存。
DatabaseManager.defaults.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
并不是将缓存设置越大越能得到好的性能J,还有参考内存消耗和其他因素。
注意:如果你运行了多个引擎实例在同一个数据库上(例如集群环境),既不能使用DODS也不能使用shark缓存
客户端接口
如何使用Shark库
客户端应用程序通过org.enhydra.shark.api.client包的接口设置使用shark库。对于一个应用程序首先应该做的是通过configure()方法配置库(这个配置将来自jar文件中的shark.conf),或者指定文件名,或者指定properties对象。在配置完org.enhydra.shark.Shark.getInstance()后,返回一个SharkInterface实例。从此刻开始,应用程序开发者可以集中精力在如何使用这些库上了,或者是得到连接,或者是执行一个分配,还或者是得到一个AdminIntercace和管理用户和组等操作。
例1:不是非常有用的work-list句柄
例子的第一行是使用conf/Shark.conf文件配置工作流引擎,然后是得到连接,成功连接上工作流服务器以后向资源对象询问这个用户有多少个分配。
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:用户、组管理
这个例子既不能在LDAP组件下运行,也不能在基于数据库组件为空时运行,你至少拥有一个组和一个用户的情况下才能运行。
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文件相对于知识库根路径的位置,然后,你需要一个PackageAdmininistration实例。
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”,创建时间为最近10分钟,活动的活动数超过3个的流程。他的String变量myvariable的值为test
/*
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被介入。一个应用程序开发者可能会有很多理由来选择外部的事物,包括用同一个数据库存储应用程序数据的方法,以避免经常地创建/销毁事物……
当然,这种处理带来了一个代价,:你必须服从用法的规则。Transaction被调用Shark.getInstance().createTransaction();方法创建。在你释放他之前,你的应用程序必须调用Shark.getInstance.unlockProcesses(st);来通知shark做内部登记。如果有任何错误出现,你必须捕捉这个抛出,然后调用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文件)
如何为一个活动写一个最后期限异常?
在shark中,最后期限异常和所有的流程变量一样,你可以使用这个特殊变量。这个变量的java类型为java.util.Date,下面是他们的描述:
lPROCESS_STARTED_TIME-流程开始时间
lACTIVITY_ACTIVATED_TIME-工作流流程中的活动或者分配创建的时间
lACTIVITY_ACCEPTED_TIME-活动中第一个分配被接受的时间
注意:
如果一个活动在接受之后被拒绝了,或者他从来就没被接受,ACTIVITY_ACCEPTED_TIME 将被设置成最大值。
下面是当最后期限异常被创建时的一些规则:
l最后期限异常一定能得到一个java.util.Date结果。
l如果shark被安装为不做最后期限评估,但是初始化最后期限限制时间评估,则ACTIVITY_ACCEPTED_TIME在异常中部能够被使用,因为他在将来将包含最大值。
l这里不因该有流程变量(XPDL中的DataField或者FormalParameter实体),他们有相同的ID。
下面是最后期限异常的一些例子:
// 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 admin应用中,如何写扩展属性使其能够更新和查看活动变量
为了在shark admin应用程序中更新活动变量(被XPDL定义),XPDL活动定义必须包含一些预定义的扩展属性。假如XPDL流程定义包含变量(XPDL DataField tag)叫作“x”,并且变量(XPDL FormalParameter 类型)叫作”input_var”。如果当活动执行时,你是一个admin用户,你能够查看这些变量,你应该定义如下的活动扩展属性:
<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的外部参考,并且设置它的属性位置和你想使用的类的全名,像这样:
...
<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>
...
可能一个好的方法是定义一个类型声明元素,如果那样的话,你能够在任何地方使用它(在创建应用程序或者子流程的FormalParameters时,你不需要时间去定义适当的数据类型)
...
<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>
...
被外部引用元素指定的类必须在shark的classpath中。
在XPDL中如何定义一些变量的初始化值为空
你应该在DataField的InitialValue元素中简单地付值:
<DataField Id="participants" IsArray="FALSE">
<DataType>
<DeclaredType Id="participants_type"/>
</DataType>
<InitialValue>null</InitialValue>
</DataField>
这能够使你使用java接口或者抽象类来作为工作流变量。而这些变量的具体实现将被一些公具代理创建。
如何制定脚本语言
目前shark指定了三种脚本语言解释程序:javascript,BeanShell和Python(最后一种没有完全测试)。为了告诉shark使用的是哪种脚本语言解析条件表达式,你应该指定包的脚本元素:
# 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会失败。
如何使用XPDL直接映射应用程序定义到特殊的工具代理上(不需要应用程序实时映射)
如果你直接在XPDL中指定什么特殊的工具代理将要被工具活动执行,你应该为XPDL应用程序定义一些扩展属性。
在每个应用程序中定义的主扩展属性,他们往往被影射到工具代理中,在这里叫作“ToolAgentClass”,而这个值也应该为类的全称。
<ExtendedAttribute Name="ToolAgentClass" Value="org.enhydra.shark.toolagent.JavaScriptToolAgent"/>
这个属性被默认的shark工具代理读取,并且他创建指定的基于这个属性的工具代理。
其他的扩展属性被指定到工具代理的实现中。并且被他们读取,JavaScript和BeanShell工具代理是丁扩展属性名称为”Script”,他的内容为要被这个代理工具执行的脚本。既然这样,你完全可以使用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中。