成都心情

  BlogJava :: 首页 ::  :: 联系 :: 聚合  :: 管理 ::
  98 随笔 :: 2 文章 :: 501 评论 :: 1 Trackbacks

 
   

    你可以从这里找到常见问题的解答。

   

数据库

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)

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(&quot;I'm going to perform operation c=&quot;+a+&quot;*&quot;+b);&#10;c=a*b;&#10;java.lang.System.out.println(&quot;The result is c=&quot;+c);"/>

    该脚本运行了变量 "a" "b" 的乘法运算,并把结果保存在 "c" 中(那些变量都是 XPDL 程序定义的形参)。 



请注意!引用、转贴本文应注明原译者:Rosen Jiang 以及出处:http://www.blogjava.net/rosen

posted on 2005-08-12 10:22 Rosen 阅读(1296) 评论(0)  编辑  收藏 所属分类: 工作流

只有注册用户登录后才能发表评论。


网站导航: