Shark 怎样...(翻译)

概 述

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

数据库


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();(文章来源 www.iocblog.net)

   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 程序定义的形参)。




文章整理:iocblog
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。

相关项目