Activiti User Guide -- Activit 用户指南 Part04

 

Chapter 5. API

第五章 API

Table of Contents

Engine API

Exception strategy

Unit testing

The activiti-webapp-init.war

Process Virtual Machine API

Engine API

引擎API

The engine API is the most common way of interacting with Activiti. You need a configuration file to get started. Then you can create aConfiguration and feed in the file as a resource or as an input stream. Then you build a ProcessEngine from the configuration. From the ProcessEngine, you can obtain the various XxxxServices that contain the workflow/BPM methods. ProcessEngine and the services objects are thread safe. So you can keep a reference to 1 of those for a whole server.

引擎API是与Activiti进行交互的最常用方式。你需要一个配置文件才能够启动引擎。你可以以资源配置文件的方式创建一个配置,也可以以输入流的方式创建一个配置,那么你就可以使用该配置文件来构建一个ProcessEngine。通过ProcessEngine你可以获取一系列包含工作流/BPM方法的XxxxServicesProcessEngine和服务对象都是线程安全的,因此你可以在整个服务器中保留对它们任何一个的引用。


ProcessEngine processEngine = new ProcessEngineBuilder()
  .configureFromPropertiesResource(configurationResource)
  .buildProcessEngine();

RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
ManagementService managementService = processEngine.getManagementService();
IdentityService identityService = processEngine.getIdentityService();
HistoryService historyService = processEngine.getHistoryService();
  We've also added a couple of classes that can provide convenience for unit testing processes in package   org.activiti.engine.test .

我们在 org.activiti.engine.test包中添加了几个类以方便对流程进行单元测试。

 

For more docs on the engine API, see the javadocs.

关于流程引擎API更多的信息可以参考javadocs

Exception strategy

异常策略

The base exception in Activiti is the ActivitiException, an unchecked exception. This exception can be thrown at all times by the API, but 'expected' exceptions that happen in specific methods are documented in the the javadocs. For example, an extract from TaskService:

ActivitiExceptionActiviti最基本的异常,它是一个unchecked异常。该异常可以在API的任何地方被抛出,在javadocs中会描述了一些方法的异常需要被‘expected’。例如,TaskService

/**
        * Called when the task is successfully executed.
        * @param taskId the id of the task to complete, cannot be null.
        * @throws ActivitiException when no task exists with the given id.
        */
        void complete(String taskId);
  In the example above, when an id is passed for which no task exists, an exception will be thrown. Also, since the javadoc explicitly states that taskId cannot be null, an ActivitiException will be thrown when null is passed.

该方法中,如果不存在所传入id的任务,那么就会抛出一个异常。同时,javadoc中也明确的指出taskId参数不可以为空,如果为空则会抛出一个ActivitiException异常。

 

Even though we want to avoid a big exception hierarchy, the following subclasses were added which are thrown in specific cases:

尽管我们极力避免一个庞大的异常体系,但是下面两个子类还是被加入进来,它们会在一些特殊用例中被抛出:

  • ActivitiWrongDbException: Thrown when the Activiti engine discovers a mismatch between the database schema version and the engine version.
  • ActivitiWrongDbException: Activiti引擎发现数据库的版本和引擎版本不一致时被抛出。
  • ActivitiOptimisticLockingException: Thrown when an optimistic locking occurs in the datastore caused by concurrent access of the same data entry.
  • ActivitiOptimisticLockingException: 由于同时访问同一条数据造成乐观锁产生时就会抛出该异常。

Unit testing

单元测试

Business processes are an integral part of software projects and they should be tested in the same way normal application logic is tested: with unit tests. Since Activiti is an embeddable Java engine, writing unit test for business processes is as simple as writing regular unit tests.

业务流程是软件项目中一个重要的部分,因此它们也应该像我们使用单元测试测试应用逻辑一样可以被测试。因为Activiti是一个嵌入式流程引擎,所以编写业务流程的单元测试就和我们编写普通单元测试一样易于编写。

 

Activiti supports both Junit versions 3 and 4 style of unit testing. In the Junit 3 style, the org.activiti.engine.test.ActivitiTestCase must be extended. This will make the processEngine and the services available through protected member fields. In the setup() of the test, the processEngine will be initialized by default with the activiti.properties resource on the classpath. To specify a different configuration file, override the getConfigurationResource() method. Process engines are be cached statically over multiple unit tests when the configuration resource is the same.

Activiti的单位测试支持Junit的版本3和版本4两种风格。使用版本3Junit时,必须使用org.activiti.engine.test.ActivitiTestCase 作为基类。这样可以使用保护字段来构建processEngineservices。在setup() 方法中,缺省流程引擎将根据classpath中的 activiti.properties 资源文件进行初始化。你可以通过复写 getConfigurationResource() 方法来使用不同的配置文件。当多个单元测试使用同一个配置资源文件时,process engines将被静态缓存。

 

By extending ActivitiTestCase, you can annotate test methods with org.activiti.engine.test.Deployment. Before the test is run, a resource file of the form testClassName.testMethod.bpmn20.xml in the same package as the test class, will be deployed. At the end of the test, the deployment will be deleted, including all related process instances, tasks, etc. The Deployment annotation also supports setting the resource location explicitly. See the Javadoc for more details.

当基于ActivitiTestCase进行单元测试时,可以使用 org.activiti.engine.test.Deployment注释来指定要进行测试的方法。在测试运行前,流程引擎会先部署测试类所在目录下一个名称为testClassName.testMethod.bpmn20.xml 流程定义文件。当测试运行结束后,该部署将会被删除,同时也会删除相关的流程实例、任务等数据。Deployment 注释也可以明确的指定资源文件所在路径。详细信息可以查看javadoc.

 

Taking all that in account, a Junit 3 style test looks as follows.

综上所述,基于Junit3的测试用例,如下所示:

public class MyBusinessProcessTest extends ActivitiTestCase {
   
  @Deployment
  public void testSimpleProcess() {
    runtimeService.startProcessInstanceByKey("simpleProcess");
    
    Task task = taskService.createTaskQuery().singleResult();
    assertEquals("My Task", task.getName());
    
    taskService.complete(task.getId());
    assertEquals(0, runtimeService.createProcessInstanceQuery().count());
  }
}     
  To get the same functionality when using the Junit 4 style of writing unit tests, the  org.activiti.engine.test.ActivitiRule  Rule must be used. Through this rule, the process engine and services are available through getters. As with the  ActivitiTestCase  (see above), including this Rule will enable the use of the  org.activiti.engine.test.Deployment  annotation (see above for an explanation of its use and configuration). Process engines are statically cached over mutliple unit tests when using the same configuration resource.

使用Junit4风格来编写单元测试也可以获得同样的功能,此时你必须采用org.activiti.engine.test.ActivitiRule 规则。这样你才能够通过ActivitiRule所提供的get方法获取到process engineserivces。和上述的ActivitiTestCase一样,当包含了该规则后就可以使用org.activiti.engine.test.Deployment 注释了。当多个单元测试使用同一个配置资源文件时,process engines将被静态缓存。

 

Following code snippet shows an example of using the Junit 4 style of testing and the usage of the ActivitiRule.

下面的实例展现了使用Junit4风格进行单元测试,以及ActivitiRule的使用方式。

public class MyBusinessProcessTest {
  
  @Rule
  public ActivitiRule activitiRule = new ActivitiRule();
  
  @Test
  @Deployment
  public void ruleUsageExample() {
    RuntimeService runtimeService = activitiRule.getRuntimeService();
    runtimeService.startProcessInstanceByKey("ruleUsage");
    
    TaskService taskService = activitiRule.getTaskService();
    Task task = taskService.createTaskQuery().singleResult();
    assertEquals("My Task", task.getName());
    
    taskService.complete(task.getId());
    assertEquals(0, runtimeService.createProcessInstanceQuery().count());
  }
}

 

The activiti-webapp-init.war

activity-webapp-init.war

The activiti-webapp-init.war can be used to easily manage process engine initialization and proper shutdown. This war is automatically added to tomcat in the setup scripts when deploying activiti to tomcat.

使用activiti-webapp-init.war可以方便管理流程引擎的初始化和proper关闭。当部署activititomcat时,该war将自动的安装到tomcat中。

 

The war contains a single ServletContextListener that has a contextInitialized and a contextDestroyed method. The contextInitialized will delegate to ProcessEngines.init(). That will look for all activiti.properties resource files on the classpath. For each configuration file found, it will create a ProcessEngine.

war中包含里了一个单独的 ServletContextListener ,该listener声明了 contextInitialized  contextDestroyed 方法。 contextInitialized 方法将调用 ProcessEngines.init()方法。在启动时将搜索classpath下所有 activiti.properties 文件。然后为每一个找到的配置文件创建一个ProcessEngine

 

The default process engine name is default.

缺省流程引擎的名称为default

 

If you have multiple such resource files on the classpath, make sure they all have different values for property process.engine.name

如果你在classpath下有多个这样的配置文件,那么请确认它们的process.engine.name是否拥有不同的值。

 

The initialized ProcessEngines can be accessed with ProcessEngines.getProcessEngine(String processEngineName)

通过ProcessEngines.getProcessEngine(String processEngineName)就可以访问到初始后的ProcessEngine

 

The contextDestroyed of the context-listener delegates to ProcessEngines.destroy(). That will properly close all initialized process engines.

context-listener contextDestroyed 方法则调用 ProcessEngines.destroy()方法,用例关闭所有已经加载的流程引擎。

Process Virtual Machine API

流程虚拟机API

The Process Virtual Machine API exposes the POJO core of the Process Virtual Machine. Reading and playing with it is interesting for education purposes to understand the internal workings of Activiti. And the POJO API can also be used to build new process languages.

流程虚拟机API则暴露了流程虚拟机的POJO核心。把玩这些理解Activiti的内部工作机制。使用POJO API你可以构建一个新流程语言。

 

For example:

例如:

PvmProcessDefinition processDefinition = new ProcessDefinitionBuilder()
  .createActivity("a")
    .initial()
    .behavior(new WaitState())
    .transition("b")
  .endActivity()
  .createActivity("b")
    .behavior(new WaitState())
    .transition("c")
  .endActivity()
  .createActivity("c")
    .behavior(new WaitState())
  .endActivity()
  .buildProcessDefinition();

PvmProcessInstance processInstance = processDefinition.createProcessInstance();
processInstance.start();

PvmExecution activityInstance = processInstance.findExecution("a");
assertNotNull(activityInstance);

activityInstance.signal(null, null);

activityInstance = processInstance.findExecution("b");
assertNotNull(activityInstance);

activityInstance.signal(null, null);

activityInstance = processInstance.findExecution("c");
assertNotNull(activityInstance);
 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,Activity是Android系统中的四大组件之一,可以用于显示View。Activity是一个与用记交互的系统模块,几乎所有的Activity都是和用户进行交互的,但是如果这样就能说Activity主要是用来显示View就不太正确了。 在深入了解Activity之前,我们先要知道一下MVC设计模式,在JAVAEE 中MVC设计模式已经很经典了,而且分的也比较清晰了,但是在Android中,好多人对MVC在Android开发中的应用不是很清楚,下面我就先来介绍一下MVC在Android开发中的应用: M(Model 模型):Model是应用程序的主体部分,所有的业务逻辑都应该写在这里,在Android中Model层与JavaEE中的变化不大,如:对数据库的操作,对网络等的操作都放在该层(但不是说它们都放在同一个包中,可以分开放,但它们统称为Model层)。 V(View 视图):是应用程序中负责生成用户界面的部分,也是在整个MVC架构中用户唯一可以看到的一层,接收用户输入,显示处理结果;在Android应用中一般采用XML文件里德界面的描述,使用的时候可以非常方便的引入,当然也可以使用JavaScript+Html等方式作为View。 C(Controller控制层)android的控制层的重任就要落在众多的activity的肩上了,所以在这里就要建议大家不要在activity中写太多的代码,尽量能过activity交割Model业务逻辑层处理。 好了,在介绍过Android应用开发中的MVC架构后,我们就可以很明确的知道,在Android中Activity主要是用来做控制的,它可以选择要显示的View,也可以从View中获取数据然后把数据传给Model层进行处理,最后再来显示出处理结果。 介绍过Activity的主要作用后,那么我们就要详细说一下Activity了。 Activity生命周期图 Activity 的生命周期是被以下的函数控制的。 public class Activity extends ApplicationContext { protected void onCreate(Bundle icicle); protected void onStart(); protected void onRestart(); protected void onResume(); protected void onFreeze(Bundle outIcicle); protected void onPause(); protected void onStop(); protected void onDestroy(); } onCreate(Bundle) 函数是你进行初始化的地方,这个也是执行 setContentView(View)函数的地方,setContentView(View)函数可以传入一个由XML 编制的UI界面,可以使UI和具体实现完全分离。 onPause()函数是处理用户离开当前 Activity 的地方。更重要的是,任何在当前 Activity中的任何改变都要在这个函数中提交。 Activity有四种状态: 活动状态,当Activity处于Stack(栈)顶时,就是手机当前的现实屏幕,这是 Activity就 处于activity或者运行状态。 运行但是失去焦点,当Activity还处于运行状态时,但是屏幕是有另外一个Activity 处于文档处于焦点状态,当前的Activity就处于pause。 停止,当Activity被另一个Activity完全覆盖的时候,就被停止了,其实就是虽然在 运行,但是用户却看不见。 结束,当Activity处于pause或者stop时,系统可以结束 Activity,回收资源,这 是Activity就是处于结束状态了。 处于结束状态的是Activity,如果要使用户可见,只要重启才可以。 Activity的响应时间 当前Activity所在的线程为主线程,它的响应时间为5秒,如果在当前运行的Activity中进行耗时的操作且响应时间起过5秒,那么程序就会报ANR错误。所以,这也是不建议在Activity中写太多复杂代码的原因之一。 当然,有些代码只能写在Activity中,不然就运行不了(它们不是生命周期方法),比如你想要获得android系统或者硬件一的些信息,就必须在Activity中写出来,如果单独写一个工具类获得不了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值