Quartz Job Scheduling Framework[翻译]第十四章. 工作流中使用 Quartz (第三部分)

四. Quartz 与 OSWorkflow 的集成


OSWorkflow 与 Quartz 集成的第一步是要改变关于 Job 的思维方式。当把 OSWorkflow 引入到你的 Quartz 应用时你需要以完全不同的方式来思考。那也不是说你当前的想法就是糟糕的或不正确的,只是与 Quartz 一同用工作流强迫你生发一些关于是什么组成 Job 的新的思维。你过去概念中的 Job 现成变成了一个 OSWorkflow 函数。你可以认为是你原有 Job 实质上存在的逻辑作为工作流中的步骤。你仍然需要使用 Quartz 的 Job,但是,当与 Quartz 框架集成工作流时,一个 Quartz Job 将用来初始化工作流。在工作流运行时,这个 Job 将会等待它直至结束。

在本章前面部分,当我们谈到串联 Job 时,每个 Job 代表了一个独立的任务。Jox X 执行后并完成一个任务,接着通知 Job Y 去执行一个有点关联却是独立的任务。在这两个任务间必须有一些依赖关系,否则你不能把它们链接在一起。

当加入工作流到这个流程中时,那些独立的 Job 就变身为工作流中的步骤了,而且你仅需要创建单个的 Job。当收到 Scheduler 的通知时,那个 Job 就起过工作流然后等待着工作流的完成。这其中有一些严格的寓意。好消息是,通过使用 OSWorkflow,你只需更少的 Quartz Job,因为早先的 Job 现在成了步骤(实际是函数)。坏消息是假如你有创建了大量的 Job,将要耗费一些工作量去转换 Job 到 OSWorkflow 的函数。

·下载和安装 OSWorkflow

你可以从它在 OpenSymphony 站点 http://www.opensymphony.com/osworkflow 的主页下载完整的发行版。从发布页的根目录获取到二进制版的 OSWorkflow 和其他第三方的库,它们在 <OSWORKFLOW_DISTRIBUTION>/lib/core 目录下。把这些二进制包扔到你的项目的 lib 目录中。这应当和 Quartz 二进制包所在的同一目录。

你必须建立两个配置文件并放置到你的 classes 目录中。第一个你需要创建的配置文件叫做 osworkflow.xml。这个文件在 OSWorkflow 启动并配置运行时环境时被加载。我们例子中的该文件如代码 14.8 中显示。

代码 14.8. osworkfllow.xml 文件用于配置 OSWorkflow 的运行时环境
1<osworkflow>
2  <persistence
3    class="com.opensymphony.workflow.spi.memory.MemoryWorkflowStore"/>
4  <factory class="com.opensymphony.workflow.loader.XMLWorkflowFactory">
5    <property name="resource" value="workflows.xml" />
6  </factory>
7</osworkflow>

假如你再看看 OSWorkflow 的文档,你会发现你可以从多种类型的持久性存储和工作流工厂中作出选择。在代码 14.8 中所用的都是最简单的并且为我们的例子工作的很好的。

配置在代码 14.8 中的工作流工厂类叫做 XMLWorkflowFactory,它包括一个称为 resource 的属性。XMLWorkflowFactory 用于加载一个包含了所有工作流的资源文件。在这里的 resource 属性的值是 workflows.xml。只要你想要多少个,就允许你可以有多少个不同的工作流。每个工作流驻留在一个单独的 XML 文件中,但是你需要以某种方式指定可用的工作流列表给 OSWorkflow 引擎。因为我们已经指定工厂为 XMLWorkflowFactory,所以框架会查看 workflows.xml 文件来得到可用的工作流并加载它们。代码 14.9 显示了我们例子里的 workflows.xml 文件。

代码 14.9. workflows.xml 文件定义了应用可用的工作流列表
1<workflows>
2  <workflow
3    name="data-import"
4    type="resource"
5    location="data-import-workflow.xml"/>
6</workflows>

代码 14.9 只列了一个工作流:data-import,它将在我们启动工作流时用作参考。实际的工作流定义是破存储在文件 data-import-workflow.xml 中的。代码 14.10 显示了 data-import 工作流。

代码 14.10. data-import 工作流被定义在一个 XML 文件中
 1<?xml version="1.0" encoding="UTF-8"?>
 2<!DOCTYPE workflow PUBLIC
 3                 "-//OpenSymphony Group//DTD OSWorkflow 2.7//EN"
 4                 "http://www.opensymphony.com/osworkflow/workflow_2_7.dtd">
 5<workflow>
 6    <initial-actions>
 7        <action id="1" name="Start Workflow">
 8            <results>
 9                <unconditional-result old-status="Finished" status="Queued"
10                    step="1" />
11            </results>
12        </action>
13    </initial-actions><br/><br/>
14    <steps>
15        <step id="1" name="Read Files">
16            <actions>
17                <action id="2" name="Get the files" auto="true">
18                    <pre-functions>
19                        <function type="class">
20                            <arg name="class.name">
21                               org.cavaness.quartzbook.chapter14.ReadFileFunction
22                            </arg>
23                        </function>
24                    </pre-functions><br/><br/>
25                    <results>
26                        <unconditional-result old-status="Finished"
27                            status="Underway" step="2" />
28                    </results>
29                </action>
30            </actions>
31        </step><br/><br/>
32        <step id="2" name="Send Email Notification">
33            <actions>
34                <action id="3" name="Get the files" auto="true">
35                    <pre-functions>
36                        <function type="class">
37                            <arg name="class.name">
38                               org.cavaness.quartzbook.chapter14.SendEmailFunction
39                            </arg>
40                        </function>
41                    </pre-functions><br/><br/>
42                    <results>
43                        <unconditional-result old-status="Finished"
44                            status="Underway" step="3" />
45                    </results>
46                </action>
47            </actions>
48        </step><br/><br/>
49        <step id="3" name="finished" />
50    </steps>
51</workflow>

定义在代码 14.10 的工作流包含两个步骤:“读文件” 和 "发 e-mail 通知"。当工作流启动后,initial-actions 块被执行,继而它调用步骤 1。当进入到步骤 1 后,org.cavaness.quartzbook.chapter14.ReadFileFunctionexecute() 方法就被调用。代码 14.11 显示了这一函数。

代码 14.11. 工作流引擎在步骤 1 其间调用 ReadFileFunction
 1public class ReadFileFunction implements FunctionProvider {
 2     static Log logger = LogFactory.getLog(ReadFileFunction.class);
 3
 4     public void execute(Map transientVars, Map args, PropertySet ps)
 5               throws WorkflowException {
 6          logger.info("Entered " + this.getClass().getName());
 7
 8          // Read the files and process the data
 9          String dirName = (String)transientVars.get("SCAN_DIR");
10          if ( dirName == null ) {
11               throw new InvalidInputException( "Scan dir not set" );
12          }
13
14          File dir = new File( dirName );
15          File[] files = dir.listFiles();
16
17          int fileCount = files.length;
18          ps.setInt( "FILE_COUNT", fileCount );
19     }
20}

ReadFileFunctionexecute() 方法完成后,工作流会转换到步骤 2。在步骤 2,org.cavaness.quartzbook.chapter14.SendEmailFunction 被调用并获得机会执行。SendEmailFunction 显示在代码 14.12 中。

代码 14.12. SendEmailFunction 在工作流的步骤 2 期间被调用
 1public class SendEmailFunction implements FunctionProvider {
 2     static Log logger = LogFactory.getLog(SendEmailFunction.class);
 3
 4     public void execute(Map transientVars, Map args, PropertySet ps)
 5               throws WorkflowException {
 6          logger.info("Entered " + this.getClass().getName());
 7
 8          int fileCount = ps.getInt("FILE_COUNT");
 9          logger.info( "File count " + fileCount );
10
11          // Email creation code not shown
12     }
13}

显然我们漏下了这个函数的实例;也没有对此多加以说明。我们假定你知道如何使用 JavaMail 发送电子邮件。 永久链接 https://yanbin.blog/quartz-job-scheduling-framework-14-3/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。