内容


FileNet P8 工作流生命周期管理和 Process Engine API 应用介绍

Comments

概述

FileNet P8 是 IBM 新一代的、统一的企业级内容和流程管理平台,它包含广泛的产品和服务,帮助用户在面向服务架构(SOA)的环境中构建,部署,运行和管理企业的内容和流程。它在分布式 (distributed),可获取性 (availability),可调控性 (scalability),安全,标准化等诸多方面都有很强的表现。它包含三大产品组:内容管理 (FileNet Content Manager),流程管理 (FileNet Business Process Manager) 和记录管理 (FileNet Records Manager) 。流程管理包含流程配置控制台 (Process Configuration Console),流程设计器 (Process Designer),流程引擎 (Process Engine),应用引擎 (Application Engine) 等产品和应用。本文内容主要涉及流程引擎(以下简称 PE)。

与 FileNet PE 相配套的有两个应用:流程管理器 (Process Administrator) 和流程跟踪器 (Process Tracker),它们可以用来监控和管理 PE 中正在运行的流程实例。但流程管理器和流程跟踪器中的概念和操作相对来说比较复杂,更适合于专门的 IT 人员,对于企业的业务人员来说,通常更希望在一个统一的业务应用里来监控和管理企业里所有的流程实例,这个业务应用将底层的 IT 技术屏蔽,而且很可能集成了其他的日常应用,如办公系统。另外,不同的企业对于流程监控和管理的业务需求很可能有差别,对用户界面的要求也有差别,如有的企业喜欢 Web2.0,有的喜欢桌面软件。因此,开发人员有必要掌握 FileNet PE 中工作流(即流程)的生命周期以及 FileNet 提供的 PE API(用于观察和改变工作流的状态),从而能够为不同的企业开发定制化的流程监控和管理软件。本文主要是为此目的而撰写,但对于想了解 FileNet PE 工作流生命周期及相关底层知识的开发者和架构师来说,本文亦有参考价值。

本文假设读者已经具有 FileNet P8 流程管理产品的一些基本知识,能够使用流程设计器创建工作流定义 (Workflow Definition),保存成内容引擎 (Content Engine,以下简称 CE) 中的文档并且转移(Transfer)至 PE 引擎,了解工作区(Workplace)的基本使用方法。

相关知识

生命周期图

一个流程会经历定义,持久化(即保存定义文档),转移(Transfer)至 PE,启动,运行,结束,版本管理等多个过程,本文介绍的是流程定义转移至 PE 后,在 PE 中启动和运行的流程实例的生命周期,而流程实例在运行过程中的主要表现是工作项(Work Item)的生命周期。

PE 数据库介绍

FileNet PE 运行时数据和状态是保存在数据库中的,这是因为 PE 里的流程都是长流程,要求当电脑发生故障重新启动之后,流程依然能够继续运行,没有任何数据损失。您可以通过查看数据库数据的变化来观察工作流和工作项内容和状态的变化。下面介绍一下 PE 数据库的基本情况,本文假设 FileNet PE 所用的数据库为 DB2,不过即使用的是其他数据库产品,本文的介绍也是类似的。

PE 数据库默认名称为 VWDB,其中的表名(不包括 DB2 的系统表)均以 VW 开头,本文关注的有下面这些表:

  • VWRoster 表 – 如 VWROSTER2_112,这里 2 代表独立区域号 (Isolated Region Number),112 为该独立区域里一个表序号,下文同。 VWRoster 表用来装载工作流实例的根工作项 (Root Work Item) 以及部分一般工作项 (Normal Work Item) 的记录,这些会在下文提到。
  • VWQueue 表 – 如 VWQUEUE2_100 。 VWQueue 表主要有两种类型,一种是 User Queue 表,一个独立区域只有一个,用来装载所有该独立区域里的用户收件箱 (My Inbox) 里的工作项的记录,这些会在下文提到,另一种是 Work Queue 表,一个独立区域可以有多个 Work Queue 表,每个对应独立区域里的一个 Work Queue,装载相应公共收件箱 (Public Inbox) 里的工作项的记录。
  • VWLog 表 – 如 VWLOG2_113 。是 PE 里的事件日志表,记录流程的启动,运行,一般工作项的打开,移动,完成等事件。

实例简介

一个流程定义里可能有许多节点 (Step),但基本的节点种类并不多,我们这里举两个非常简单的流程例子,每个例子只包含一个启动节点 (Launch Step) 和一个通用节点 (General Step),这已经可以用来讲述本文主要内容了。而且,我们只讲基本知识,不会面面俱到,流程定义细节除非特别指出,否则用的都是默认值。

我们有 5 个用户 (User):

  • administrator,属于 Administrators 组 (Group)
  • jordan, mark, david,属于 Checkers 组
  • bill,属于 Adjustors 组

Checkers 组有权访问 Checkers 工作队列 (Work Queue),Adjustors 组有权访问 Adjustors 工作队列。工作队列是在独立区域 (Isolated Region) 里定义的一种组件,其中保存某些用户或组的公共工作项。关于独立区域的设置,请参考 FileNet P8 平台文档 – Process Configuration Console (http://<host>:<port>/ecm_help/pe_help/config.htm) 。

第一个流程的定义图如下。

图 1. 工作流定义 SampleParticipantFlow
图 1. 工作流定义 SampleParticipantFlow
图 1. 工作流定义 SampleParticipantFlow

定义文档的名称为 SampleParticipantFlow 。节点 ParticipantStep 的目标 (Step Destination) 是 Participants: david, jordan 和 mark 。

第二个流程定义图如下。

图 2. 工作流定义 SampleWorkQueueFlow
图 2. 工作流定义 SampleWorkQueueFlow
图 2. 工作流定义 SampleWorkQueueFlow

定义文档的名称为 SampleWorkQueueFlow 。节点 WorkQueueStep 的目标是 Checkers 工作队列 (Work Queue) 。

您可以下载这两个流程定义文件并通过流程设计器导入到您的 CE 中(参见参考资源)。

我们假定流程定义已经经过了创建,编辑,保存在 CE 中,转移至 PE 中这些阶段,并且假定流程所运行的独立区域使用的是默认的用户收件箱 (User Inbox), 登记簿 (Roster) 和事件日志 (EventLog) 。

以下对流程实例和工作项生命周期中的每个步骤的解说都有三个方面:工作区 (Workplace) 中的操作,VWDB 数据库中相应的数据和变化,相应的用 PE API 查看或管理流程实例或工作项的代码片段和代码执行结果。数据库数据有些时候比较容易观察,有些时候由于涉及到多个数据库表的关联操作而不太容易观察,本文在讲解例子的时候列出了作者的一些观察结果,但只是起到抛砖引玉的作用,不会列出所有的观察结果,读者有兴趣可以进一步尝试。对于代码这一方面,有的介绍的详细些,有的介绍的简单些,避免赘述。下文中的代码都是假设 VWSession 已经通过 administrator 用户获取。另外,代码清单中执行结果(输出)附在代码的后面并用不同的字体显示。

流程启动

工作区操作

我们同时启动两个流程例子。

以 administrator 用户登录工作区,定位到工作流定义文档所在的位置,右键选中工作流定义文档 SampleParticipantFlow,然后选择 Launch,如下图所示。

图 3. 启动工作流(第一步)
图 3. 启动工作流(第一步)
图 3. 启动工作流(第一步)

在弹出的界面里点 Launch 链接,如下图所示。

图 4. 启动工作流(第二步)
图 4. 启动工作流(第二步)
图 4. 启动工作流(第二步)

输入主题 (Subject) ‘ SampleParticipantFlowInstance1 ’,然后点 Launch 按钮完成流程启动,如下图所示。

图 5. 启动工作流(第三步)
图 5. 启动工作流(第三步)
图 5. 启动工作流(第三步)

以同样的方式启动流程 SampleWorkQueueFlow,输入主题’ SampleWorkQueueFlowInstance1 ’。

主题可以用来跟踪流程实例运行的状态。

数据库变化

一个根工作项记录被插入到了 VWRoster 表。

代码

清单 1. 通过 SQL 语句查看根工作项记录
 select * from F_SW.VWROSTER2_112 
 where F_WobNum=F_WorkFlowNumber and F_SUBJECT='SampleParticipantFlowInstance1'; 
 F_WOBNUM F_WORKCLASSID F_UNIQUEID F_TIMEOUT F_SERVERID F_BASEVIEWID F_TAG F_TAGTYPE 
 F_ORIGINATOR F_WORKFLOWNUMBER F_STARTTIME F_SUBJECT F_TRACKERSTATUS 

 x'59304C5DFA7D2A47A621C41A6BE08AF0' 15 +7.49000000000000E+002 - 0 101 * 0. 50 
 x'59304C5DFA7D2A47A621C41A6BE08AF0' 1223475598 SampleParticipantFlowInstance1 

     0 1 record(s) selected.
清单 2. 通过 PE API 查看根工作项
 public void testRetrieveWorkflowInstance() throws VWException { 
 VWRoster vwRoster = vwSession.getRoster("DefaultRoster"); 
 String filter = "F_WobNum=F_WorkFlowNumber and F_SUBJECT=:subject"; 
 String subject = "SampleParticipantFlowInstance1"; 
 Object[] substitutionVars = new Object[] { subject  }; 
 VWRosterQuery rQuery = vwRoster.createQuery( 
	    null, null, null, VWRoster.QUERY_NO_OPTIONS, 
	    filter, substitutionVars, 
	    VWFetchType.FETCH_TYPE_WORKOBJECT); 
	 while (rQuery.hasNext()) { 
	    VWWorkObject workObject = (VWWorkObject) rQuery.next(); 
        printFlowInstance(workObject);        	      
    } 
 } 

 private void printFlowInstance(VWWorkObject flowInstance) throws VWException { 
	 System.out.println("\t*******************"); 
	 System.out.println("\tWork Class Name: " + flowInstance.getWorkClassName()); 
	 System.out.println("\tWorkflow Number: " + flowInstance.getWorkflowNumber()); 
	 System.out.println("\tSubject: " + flowInstance.getSubject());  
	 System.out.println("\tLaunch Date: " + flowInstance.getLaunchDate()); 
	 System.out.print("\tAll Data Fields: "); 
	 VWDataField[] dataFields = flowInstance.getDataFields( 
	    VWWorkObject.FIELD_USER_AND_SYSTEM_DEFINED, 
	    VWWorkObject.FIELD_USER_AND_SYSTEM_DEFINED); 
	 printDataFields(dataFields);  
 } 

 private void printDataFields(VWDataField[] dataFields) throws VWException { 
          for (int i = 0; i < dataFields.length; i++) {            		
 System.out.print(dataFields[i].getName() + "=" + dataFields[i].getValue() + ", "); 
          } 
          System.out.println("\n"); 		
 } 

 ********************************************************** 
 Work Class Name: SampleParticipantFlow 
 Workflow Number: 59304C5DFA7D2A47A621C41A6BE08AF0 
 Subject: SampleParticipantFlowInstance1 
 Launch Date: Wed Oct 08 22:19:58 CST 2008 
 All Data Fields: F_WobNum=59304C5DFA7D2A47A621C41A6BE08AF0, F_WorkSpaceId=241, 
 F_Locked=0, F_LockMachine=0, F_LockUser=0, F_BindPending=0, F_BoundUser=0, 
 F_BoundMachine=0, F_Tag=*, F_OperationId=-1, F_WorkClassId=15, F_QueueWPClassId=-6, 
 F_InstrSheetId=-2, F_WorkOrderId=3, F_Class=SampleParticipantFlow, F_Operation=, 
 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Originator=50, 
 F_ParentWobNum=00000000000000000000000000000000, F_SplitLeg=-1, F_TrackerStatus=0, 
 F_Overdue=0, F_Response=, F_TransferUser=50, F_StepProcId=5, F_MinMilestone=0, 
 F_MaxMilestone=0, F_Occurrence=1223475599, F_StepName=ParticipantStep, 
 F_StepDescription=, F_LastErrorNumber=0, F_LastErrorText=, F_InstrSheetName=Workflow, 
 F_WsPortType=, F_WsOperation=, F_WsCorrelation=, F_WorkClassRevision=1, F_WFDeadline=0, 
 F_WFReminder=0, F_Trackers=[Ljava.lang.String;@1ee40a4, F_Comment=, 
 F_Responses=[Ljava.lang.Integer;@d5e270, F_ResponseCount=0, 
 F_Subject=SampleParticipantFlowInstance1, 
 F_SourceDoc=3:3:P8ObjectStore:{E9B66E22-99BF-49BB-BDFF-523C0060593C}: 
	 {D28FD1D2-1A96-43E4-9DB6-18ADE9829F8A},

这里需要注意的是 VWWorkObject 类表示工作项 (Work Item),可以是根工作项或一般工作项,其中根工作项中保存了工作流实例的基本信息。以上代码片段查找到的就是根工作项。判断一个工作项是否为根工作项的标准是:如果它的 F_WobNum 数据字段值等于 F_WorkFlowNumber 数据字段值,它就是一个根工作项,否则它是一个一般工作项。下文如果不特别指出,工作项指的都是一般工作项。

您可以看到 VWWorkObject 中数据字段比直接用 SQL 语句查询数据库表得到的记录的数据字段要多,这是因为 VWWorkObject 中的数据来自多个数据库表的集成,PE API 自动帮您把相关数据集成到 VWWorkObject 中。

另外一个常见需求:查看一个工作流有多少实例在运行。

清单 3. 列出一个工作流的所有实例
 public void testListWorkflowInstancesByWorkClassName() throws VWException { 
	 String workClassName = "SampleParticipantFlow"; 
	 VWRoster vwRoster = vwSession.getRoster("DefaultRoster"); 
                      String filter = "F_WobNum = F_WorkFlowNumber"; 
 Object[] substitutionVars = null; VWRosterQuery rQuery = vwRoster.createQuery( 
	 null, null, null, 
	 VWRoster.QUERY_NO_OPTIONS, filter, substitutionVars, 
	 VWFetchType.FETCH_TYPE_WORKOBJECT); 
 while (rQuery.hasNext()) { VWWorkObject flowInstance = (VWWorkObject) rQuery.next(); 
 if (workClassName.equals(flowInstance.getWorkClassName())) 
            { printFlowInstance(flowInstance); } } 
 }

这段代码的输出和 清单 2中的一样。这里 workClassName 指的是工作流定义转移至 PE 时所起的名字。

流程运行

主要介绍工作项生命周期。

工作项的产生和分派 (assign)

工作区操作

流程例子 SampleParticipantFlow 的节点 ParticipantStep 的节点目标为 Participants,对于这种情况,当流程实例运行到该节点时,会为每位参与者 (participant) 创建一个工作项并发送到他(她)的收件箱 (My Inbox) 里,他(她)可以登录到工作区,到任务 (Tasks) 版块的“我的收件箱” (My Inbox) 里查看这个工作项,这个工作项只有他(她)自己可以看到。

在这个例子中,有三个工作项被创建,分别发送到 david, jordan 和 mark 的收件箱里,下图显示了 david 的收件箱。

图 6. david 的收件箱
图 6. david 的收件箱
图 6. david 的收件箱

流程例子 SampleWorkQueueFlow 的节点 WorkQueueStep 的节点目标为工作队列 Checkers,对于这种情况,当流程实例运行到该节点时,只会创建一个工作项并发送到公共收件箱 (Public Inbox) Checkers 里。任何有权访问 Checkers 公共收件箱的用户都可以在登录到工作区之后,到任务版块的“公共收件箱” (Public Inboxes) 里找到 Checkers 公共收件箱,打开 Checkers 就可以看到那个工作项。下图显示了 jordan 打开 Checkers 公共收件箱。

图 7. 公共收件箱 Checkers
图 7. 公共收件箱 Checkers
图 7. 公共收件箱 Checkers

对于一个可见的工作项,用户可以在工作区中查看它的属性 (Properties),附件 (Attachments),数据字段 (Data Fields) 等,还可以对它进行操作,如打开 (Open) 它,完成 (Complete) 它或重新分配 (Reassign) 它给别的用户,这些会在接下来的几个小节中讲解。

数据库变化

对于流程例子 SampleParticipantFlow 目标为 Participants 的节点,当只有一个用户 (User) 参与的时候,一个工作项记录被插入到 User Queue 表;当有多个用户参与的时候,对应每个参与者,一个工作项记录被分别插入到 User Queue 表和 VWRoster 表。

对于流程例子 SampleWorkQueueFlow 目标为 Work Queue 的节点,一个工作项记录被插入到了 Checkers 工作队列所对应的 Work Queue 表。

我们可以总结:所有的工作项记录都存在 VWQueue 表里 (User Queue 表或 Work Queue 表 ),但不是所有的工作项记录都存在 VWRoster 表里;然而,所有的根工作项记录都存在 VWRoster 表而非 VWQueue 表里。

代码

关于查找工作项,有三个常见的需求。

一个是查看某用户收件箱里有哪些工作项正在等待处理(一个用户可能同时参与多个流程实例,因而他(她)的收件箱里可能有多个工作项)。

清单 4. 查看 mark 的收件箱
 public void testListUserInboxWorkItems() throws VWException { 
 String userName = "mark"; 
 String[] queueNames = vwSession.fetchQueueNames( 
 VWSession.QUEUE_USER_CENTRIC); 
 for (int i = 0; i < queueNames.length; i++) { 
	   String queueName = queueNames[i]; 
 VWQueue vwQueue = vwSession.getQueue(queueName); 
			
	   int queryFlags = VWQueue.QUERY_READ_LOCKED; 
	   if (queueName.startsWith("Inbox(")) { 
	       VWQueueQuery qQuery = vwQueue.createQuery( 
	           null, null, null, queryFlags, null, null, 
 VWFetchType.FETCH_TYPE_WORKOBJECT); 
 while (qQuery.hasNext()) { 
 VWWorkObject workObject = (VWWorkObject) qQuery.next(); 
 VWParticipant participant = workObject.getParticipantNamePx(); 
 if (participant != null & userName.equals(participant.getParticipantName())) 
 { 
 printNormalWorkObject(workObject); 
 }    	 
 } 
 } 
 } 
 } 

 private void printNormalWorkObject(VWWorkObject workObject) throws VWException { 
 System.out.println("\t*****************************"); 
 System.out.println("\tWork Object Number: " + workObject.getWorkObjectNumber()); 
 System.out.println("\tWork Object Subject: " + workObject.getSubject()); 
 System.out.println("\tWorkflow Name: " + workObject.getWorkflowName()); 
 System.out.println("\tWorkflow Number: " + workObject.getWorkflowNumber()); 
 System.out.println("\tWorkflow Map Name: " + workObject.getCallMap()); 
 System.out.println("\tWorkflow Step Name: " + workObject.getStepName()); 
 System.out.print("\tAll Data Fields: "); 
 VWDataField[] dataFields = workObject.getDataFields( 
 VWWorkObject.FIELD_USER_AND_SYSTEM_DEFINED, 
	   VWWorkObject.FIELD_USER_AND_SYSTEM_DEFINED); 
 printDataFields(dataFields); 	
 } 

       ***************************************** 
 Work Object Number: 2CA9351E1819C34480A59DF3BF548DD0 
 Work Object Subject: SampleParticipantFlowInstance1 
 Workflow Name: SampleParticipantFlow 
 Workflow Number: 59304C5DFA7D2A47A621C41A6BE08AF0 
 Workflow Map Name: null 
 Workflow Step Name: ParticipantStep 
 All Data Fields: F_WobNum=2CA9351E1819C34480A59DF3BF548DD0, F_WorkSpaceId=241, 
 F_Locked=0, F_LockMachine=0, F_LockUser=0, F_BindPending=0, F_BoundUser=257, 
 F_BoundMachine=0, F_Tag=*, F_OperationId=-1, F_WorkClassId=15, F_QueueWPClassId=1, 
 F_InstrSheetId=-2, F_WorkOrderId=3, F_Class=SampleParticipantFlow, F_Operation=, 
 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Originator=50, 
 F_ParentWobNum=59304C5DFA7D2A47A621C41A6BE08AF0, F_SplitLeg=257, F_TrackerStatus=0, 
 F_Overdue=0, F_Response=, F_TransferUser=50, F_StepProcId=5, F_MinMilestone=0, 
 F_MaxMilestone=0, F_Occurrence=1223475599, F_StepName=ParticipantStep, 
 F_StepDescription=, F_LastErrorNumber=0, F_LastErrorText=, 
 F_InstrSheetName=Workflow, F_WsPortType=, F_WsOperation=, 
 F_WsCorrelation=, F_WorkClassRevision=1, F_WFDeadline=0, F_WFReminder=0, 
 F_Trackers=[Ljava.lang.String;@e222eb, F_Comment=, 
 F_Responses=[Ljava.lang.Integer;@62af46, F_ResponseCount=0, 
 F_Subject=SampleParticipantFlowInstance1, 
 F_SourceDoc=3:3:P8ObjectStore:{E9B66E22-99BF-49BB-BDFF-523C0060593C}: 
	    {D28FD1D2-1A96-43E4-9DB6-18ADE9829F8A},

另一个是查看某工作队列里有哪些正在等待处理的工作项。

清单 5. 查看 Checkers 工作队列
 public void testListWorkQueueWorkItems() throws VWException { 
 String workQueueName = "Checkers"; 
 String[] queueNames = vwSession.fetchQueueNames(VWSession.QUEUE_PROCESS); 
 for (int i = 0; i < queueNames.length; i++) { 
 String queueName = queueNames[i]; 
 VWQueue vwQueue = vwSession.getQueue(queueName); 
	   int queryFlags = VWQueue.QUERY_READ_LOCKED; 
	   if (workQueueName.equals(queueName)) { 
	       VWQueueQuery qQuery = vwQueue.createQuery( 
	           null, null, null, queryFlags, null, null, 
 VWFetchType.FETCH_TYPE_WORKOBJECT); 
	       while (qQuery.hasNext()) { 
 VWWorkObject workObject = (VWWorkObject) qQuery.next(); 
         printNormalWorkObject(workObject); 
	       } 
	   } 	
 } 		
 } 

 ********************************************************* 
	 Work Object Number: 78C985FD93FF404BB6989D79E35CFA7E 
	 Work Object Subject: SampleWorkQueueFlowInstance1 
	 Workflow Name: SampleWorkQueueFlow 
	 Workflow Number: 78C985FD93FF404BB6989D79E35CFA7E 
	 Workflow Map Name: null 
	 Workflow Step Name: WorkQueueStep 
	 All Data Fields: F_WobNum=78C985FD93FF404BB6989D79E35CFA7E, F_WorkSpaceId=262, 
	 F_Locked=0, F_LockMachine=0, F_LockUser=0, F_BindPending=0, F_BoundUser=0, 
	 F_BoundMachine=0, F_Tag=*, F_OperationId=-1, F_WorkClassId=16, 
	 F_QueueWPClassId=6, F_InstrSheetId=-2, F_WorkOrderId=3, 
	 F_Class=SampleWorkQueueFlow, F_Operation=, 
	 F_WorkFlowNumber=78C985FD93FF404BB6989D79E35CFA7E, F_Originator=50, 
	 F_ParentWobNum=00000000000000000000000000000000, F_SplitLeg=-1, 
	 F_TrackerStatus=0, F_Overdue=0, F_Response=, F_TransferUser=50, 
	 F_StepProcId=5, F_MinMilestone=0, F_MaxMilestone=0, F_Occurrence=1223475753, 
	 F_StepName=WorkQueueStep, F_StepDescription=, 
                     F_LastErrorNumber=0, F_LastErrorText=, 
	 F_InstrSheetName=Workflow, F_WsPortType=, F_WsOperation=, F_WsCorrelation=, 
	 F_WorkClassRevision=1, F_WFDeadline=0, F_WFReminder=0, 
	 F_Trackers=[Ljava.lang.String;@54643, F_Comment=, 
	 F_Responses=[Ljava.lang.Integer;@481958, F_ResponseCount=0, 
	 F_Subject=SampleWorkQueueFlowInstance1, 
 F_SourceDoc=3:3:P8ObjectStore:{2B4580BC-EBA5-4370-BC79-DF3B36F3C328}: 
	    {15F32C47-A80D-4792-92C1-A4BBCBC96AD1},

再一个是查看一个流程实例当前有多少工作项正在等待处理。

清单 6. 查看一个流程实例的活动工作项
 public void testListWorkflowInstanceWorkItems() throws VWException { 
 String workflowNumber = "59304C5DFA7D2A47A621C41A6BE08AF0"; 
 String[] queueNames = vwSession.fetchQueueNames( 
 VWSession.QUEUE_PROCESS | VWSession.QUEUE_USER_CENTRIC); 
 for (int i = 0; i < queueNames.length; i++) { 
 String queueName = queueNames[i]; 
	   VWQueue vwQueue = vwSession.getQueue(queueName); 			
	   int queryFlags = VWQueue.QUERY_READ_LOCKED; 
	   VWQueueQuery qQuery = vwQueue.createQuery( 
 null, null, null, queryFlags, null, null, VWFetchType.FETCH_TYPE_WORKOBJECT); 
	   while (qQuery.hasNext()) { 
	       VWWorkObject workObject = (VWWorkObject) qQuery.next(); 
	       if (workflowNumber.equals(workObject.getWorkflowNumber())) { 
 printNormalWorkObject(workObject); 
 }    	 
	   } 						
 } 			
 } 

 ********************************************************* 
	 Work Object Number: 4F9A0983DDDC6B438EEC6DF1D40FC203 
	 Work Object Subject: SampleParticipantFlowInstance1 
	 Workflow Name: SampleParticipantFlow 
	 Workflow Number: 59304C5DFA7D2A47A621C41A6BE08AF0 
	 Workflow Map Name: null 
	 Workflow Step Name: ParticipantStep 
	 All Data Fields: F_WobNum=4F9A0983DDDC6B438EEC6DF1D40FC203, F_WorkSpaceId=241, 
	 F_Locked=0, F_LockMachine=0, F_LockUser=0, F_BindPending=0, F_BoundUser=255, 
	 F_BoundMachine=0, F_Tag=*, F_OperationId=-1, F_WorkClassId=15, 
	 F_QueueWPClassId=1, F_InstrSheetId=-2, F_WorkOrderId=3, 
	 F_Class=SampleParticipantFlow, F_Operation=, 
	 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Originator=50, 
	 F_ParentWobNum=59304C5DFA7D2A47A621C41A6BE08AF0, F_SplitLeg=255, 
	 F_TrackerStatus=0, F_Overdue=0, F_Response=, F_TransferUser=50, 
	 F_StepProcId=5, F_MinMilestone=0, F_MaxMilestone=0, F_Occurrence=1223475599, 
	 F_StepName=ParticipantStep, F_StepDescription=, F_LastErrorNumber=0, 
	 F_LastErrorText=, F_InstrSheetName=Workflow, F_WsPortType=, F_WsOperation=, 
	 F_WsCorrelation=, F_WorkClassRevision=1, F_WFDeadline=0, F_WFReminder=0, 
	 F_Trackers=[Ljava.lang.String;@e15a69, F_Comment=, 
	 F_Responses=[Ljava.lang.Integer;@f6af3b, F_ResponseCount=0, 
	 F_Subject=SampleParticipantFlowInstance1, 
	 F_SourceDoc=3:3:P8ObjectStore:{E9B66E22-99BF-49BB-BDFF-523C0060593C}: 
	 {D28FD1D2-1A96-43E4-9DB6-18ADE9829F8A}, 

	 ********************************************************* 
	 Work Object Number: FE20BFB3C16A964981B7270D8A1CB4CA 
	 Work Object Subject: SampleParticipantFlowInstance1 
	 Workflow Name: SampleParticipantFlow 
	 Workflow Number: 59304C5DFA7D2A47A621C41A6BE08AF0 
	 Workflow Map Name: null 
	 Workflow Step Name: ParticipantStep 
	 All Data Fields: F_WobNum=FE20BFB3C16A964981B7270D8A1CB4CA, F_WorkSpaceId=241, 
	 F_Locked=0, F_LockMachine=0, F_LockUser=0, F_BindPending=0, F_BoundUser=256, 
	 F_BoundMachine=0, F_Tag=*, F_OperationId=-1, F_WorkClassId=15, 
	 F_QueueWPClassId=1, F_InstrSheetId=-2, F_WorkOrderId=3, 
	 F_Class=SampleParticipantFlow, F_Operation=, 
	 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Originator=50, 
	 F_ParentWobNum=59304C5DFA7D2A47A621C41A6BE08AF0, F_SplitLeg=256, 
	 F_TrackerStatus=0, F_Overdue=0, F_Response=, F_TransferUser=50, 
	 F_StepProcId=5, F_MinMilestone=0, F_MaxMilestone=0, F_Occurrence=1223475599, 
	 F_StepName=ParticipantStep, F_StepDescription=, F_LastErrorNumber=0, 
	 F_LastErrorText=, F_InstrSheetName=Workflow, F_WsPortType=, F_WsOperation=, 
	 F_WsCorrelation=, F_WorkClassRevision=1, F_WFDeadline=0, F_WFReminder=0, 
	 F_Trackers=[Ljava.lang.String;@16a5d72, F_Comment=, 
	 F_Responses=[Ljava.lang.Integer;@1d07e4, F_ResponseCount=0, 
	 F_Subject=SampleParticipantFlowInstance1, 
	 F_SourceDoc=3:3:P8ObjectStore:{E9B66E22-99BF-49BB-BDFF-523C0060593C}: 
	 {D28FD1D2-1A96-43E4-9DB6-18ADE9829F8A}, 

	 ********************************************************* 
	 Work Object Number: 2CA9351E1819C34480A59DF3BF548DD0 
	 Work Object Subject: SampleParticipantFlowInstance1 
	 Workflow Name: SampleParticipantFlow 
	 Workflow Number: 59304C5DFA7D2A47A621C41A6BE08AF0 
	 Workflow Map Name: null 
	 Workflow Step Name: ParticipantStep 
	 All Data Fields: F_WobNum=2CA9351E1819C34480A59DF3BF548DD0, F_WorkSpaceId=241, 
	 F_Locked=0, F_LockMachine=0, F_LockUser=0, F_BindPending=0, F_BoundUser=257, 
	 F_BoundMachine=0, F_Tag=*, F_OperationId=-1, F_WorkClassId=15, 
	 F_QueueWPClassId=1, F_InstrSheetId=-2, F_WorkOrderId=3, 
	 F_Class=SampleParticipantFlow, F_Operation=, 
	 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Originator=50, 
	 F_ParentWobNum=59304C5DFA7D2A47A621C41A6BE08AF0, F_SplitLeg=257, 
	 F_TrackerStatus=0, F_Overdue=0, F_Response=, F_TransferUser=50, 
	 F_StepProcId=5, F_MinMilestone=0, F_MaxMilestone=0, F_Occurrence=1223475599, 
	 F_StepName=ParticipantStep, F_StepDescription=, F_LastErrorNumber=0, 
	 F_LastErrorText=, F_InstrSheetName=Workflow, F_WsPortType=, F_WsOperation=, 
	 F_WsCorrelation=, F_WorkClassRevision=1, F_WFDeadline=0, F_WFReminder=0, 
	 F_Trackers=[Ljava.lang.String;@1f13b08, F_Comment=, 
	 F_Responses=[Ljava.lang.Integer;@5a936b, F_ResponseCount=0, 
	 F_Subject=SampleParticipantFlowInstance1, 
	 F_SourceDoc=3:3:P8ObjectStore:{E9B66E22-99BF-49BB-BDFF-523C0060593C}: 
	 {D28FD1D2-1A96-43E4-9DB6-18ADE9829F8A},

一些常用的数据字段的意思:

  • F_WobNum – 工作项号(对于根工作项,它的值和 F_WorkFlowNumber 相同 )
  • F_WorkFlowNumber – 工作流实例号
  • F_Class – 转移至 PE 中的工作流定义名
  • F_WorkClassId – 转移至 PE 中的工作流定义 ID
  • F_InstrSheetId – 工作流定义中的图 (Map) 定义 ID
  • F_WorkOrderId – 图定义中的节点定义 ID
  • F_Locked – 工作项是否被加锁

工作项内容查看

工作区操作

在工作区查看工作项内容可以有两种方式,一种是只读性质的查看 (View) 工作项内容,通过点击工作项名字 (Name) 旁边的’ Get info for …’按钮(见图 6)来实现,结果如下图所示。

图 8. 查看工作项信息
图 8. 查看工作项信息
图 8. 查看工作项信息

另一种是可编辑性质的打开工作项,通过直接点击工作项名字链接(见图 6)实现,结果如下图所示。

图 9. 打开工作项
图 9. 打开工作项
图 9. 打开工作项

需要注意的是只读性查看工作项内容不会给工作项加锁,打开工作项则会加锁。加锁和解锁会在下面介绍。

数据库

从数据库直接查看工作项信息比较复杂,暂不描述。

代码

上一小节已经介绍了工作项的数据字段查看,您还可以调用 VWWorkObject 的 getXXX 以及 fetchXXX 方法来获取其它有关工作项的信息。

为工作项加锁 (Lock) 和解锁 (Unlock)

工作区操作

在工作区里,当您打开一个工作项后,这个工作项便被加锁了 (locked),此时其他用户不能再打开这个工作项(这通常出现在多个用户有权限打开同一个工作项的情况下,如公共收件箱里的工作项)。下图为 david 打开 Checkers 公共收件箱里的工作项 SampleWorkQueueFlowInstance1 之后,jordan 进入工作区打开 Checkers 公共收件箱时所看到的情形。

图 10. 工作项加锁
图 10. 工作项加锁
图 10. 工作项加锁

对比图 7,您可以看到工作项名字左边多了一个锁图标。

此时如果 jordan 点击该工作项名字链接,一个错误页面会弹出,如下图所示。

图 11. 无法打开被别人加了锁的工作项
图 11. 无法打开被别人加了锁的工作项
图 11. 无法打开被别人加了锁的工作项

在工作区里要想解锁工作项,有两种方式,一种是打开它的用户通过 Close 按钮关闭了它的编辑界面,或者点击 Complete 按钮完成了它,另一种方式是其他用户点击’ Get info for xxx ’按钮(注意这不受加锁的影响)弹出任务信息页面,然后在该页面对该工作项进行重新分配 (Reassign) 或移动 (Move) 操作。

数据库

从数据库直接查看锁状态,比较复杂,暂不描述。

不建议通过直接修改数据库数据的方式来给工作项加锁解锁。

代码

查看锁状态可以通过查看 VWWorkObject 与锁有关的数据字段,如 F_Locked, F_LockUser 等,也可以通过调用 VWWorkObject 的 fetchLockedStatus,getLockedUser 等方法来实现。

加锁解锁可以通过调用 VWWorkObject 的 doLock 和 doSave 方法来实现。

工作项内容编辑

工作区操作

要修改工作项内容,比如加上评论 (Comments) 或选择响应 (Response),只需要打开它并进行编辑,如图 9 所示。编辑完之后,可以点 Apply 按钮保存修改,或点 Close 按钮丢弃修改。编辑工作项不会导致它的完结,编辑工作项与重新分配和返还工作项操作结合可以实现多位用户依次在一个工作项上工作,最终由一位用户完成它。

数据库

不建议通过直接修改数据库数据的方式来编辑工作项内容。

代码

通过调用 VWWorkObject 的 setComment 或 setSelectedResponse 等方法来改变工作项内容,然后通过调用 doSave 方法保存修改。

完成 (Complete) 工作项

工作区操作

当打开工作项(如图 9)之后,无论您是否编辑它,您都可以完成它,这是通过点击 Complete 按钮来实现的。完成工作项首先会自动保存对它的编辑。

为了方便下文描述,我们在这里暂不进行完成工作项操作。

数据库变化

当一个工作项被完成后,它对应的数据库记录被从 VWRoster 和 / 或 VWQueue 表里删除。

代码

可以通过调用 VWWorkObject 的 doDispatch 方法来完成工作项。

移动 (Move) 和返还 (Return) 工作项

工作区操作

您可以将一个公共收件箱里的工作项移动到您的(个人)收件箱里,这样可以稍后再去完成它而不必担心别的用户对它进行操作。对于 SampleWorkQueueFlow 这个例子,jordan 登录到工作区后,在任务版块里点击公共收件箱链接,并打开 Checkers 公共收件箱,如图 7 所示。此时他可以点击工作项旁边的’ Get info for xxx ’按钮进入任务信息界面,然后点击 Move to Inbox 链接来完成工作项移动,如下图所示。他也可以打开工作项,然后在弹出的页面里点击 Move to Inbox 链接完成工作项移动。

图 12. 移动工作项
图 12. 移动工作项
图 12. 移动工作项

在(个人)收件箱里的工作项如果来自于公共收件箱,那么它可以被返还到原来的公共收件箱里。接着上面的例子讲,jordan 在任务版块里打开“我的收件箱 (My Inbox) ”,如下图所示。

图 13. 工作项 SampleWorkQueueFlowInstance1 被移动了
图 13. 工作项 SampleWorkQueueFlowInstance1 被移动了
图 13. 工作项 SampleWorkQueueFlowInstance1 被移动了

此时他可以点击工作项旁边的’ Get info for xxx ’按钮进入任务信息界面,然后点击 Return 链接来完成返还,如下图所示,也可以打开工作项,然后在弹出的页面里点击 Return 链接完成返还。

图 14. 返还工作项
图 14. 返还工作项
图 14. 返还工作项

数据库变化

移动操作导致相应的工作项记录从 Work Queue 表(这里对应 Checkers 公共收件箱)删除并插入到 User Queue 表。返还操作相反。

代码

通过调用 VWWorkObject 的 doReassign 和 doReturnToSource 方法来实现工作项的移动和返还。

重新分配 (Reassign) 和返还 (Return) 工作项

工作区操作

一个工作项可以被重新分配给其他用户来编辑或完成。重新分配在工作区中的操作是,点击工作项旁边的’ Get info for xxx ’按钮进入任务信息界面,如图 12 所示,或者打开工作项,然后在弹出的页面里点击 Reassign 链接。此时弹出重新分配页面,在此页面输入用户搜索字符串,如 bi,点 Search 按钮,这里搜索结果为 bill,他被默认选中了,接下来点 Accept 按钮完成重新分配,如下图所示。

图 15. 重新分配工作项
图 15. 重新分配工作项
图 15. 重新分配工作项

这时该工作项已经被重新分配给 bill 了,使用 bill 的账户登录工作区,在他的个人收件箱里就可以看到该工作项了,如下图所示。

图 16. 工作项被重新分配了
图 16. 工作项被重新分配了
图 16. 工作项被重新分配了

返还别人重新分配过的工作项,操作步骤类似返还移动过的工作项,这里就不赘述了。

数据库变化

工作项记录中与用户相关的数据字段有改动。

对于重新分配操作,如果源工作项在公共收件箱内,则相应工作项记录从 Work Queue 表(这里对应 Checkers 公共收件箱)删除并插入到 User Queue 表。返还操作相反。

代码

通过调用 VWWorkObject 的 doReassign 和 doReturnToSource 方法来实现工作项的重新分配和返还。

其他工作项管理操作

还有一些其他工作项管理操作需要在流程管理器或流程跟踪器里完成,如结束 (Terminate) 工作项。这些操作也可以通过 PE API 来完成,如调用 VWWorkObject 的 doTerminate() 方法。这些操作也会造成数据库数据变化,这里就不赘述了。

流程结束

工作区操作

当一个流程实例走完了所有的节点,它就结束了。

数据库变化

流程实例的根工作项记录被从 VWRoster 表里删除。

代码

清单1清单2,但没有结果输出,因为根工作项已经被删除了。

其他常用工作流管理功能

显示工作流定义

工作区操作

以 administrator 用户登录工作区,定位到工作流文档 SampleParticipantFlow,如图 3 所示。点击它的标题 (Title) 链接进入流程设计器,如下图所示。

图 17. 显示工作流定义
图 17. 显示工作流定义
图 17. 显示工作流定义

数据库

工作流定义没有保存在数据库中,而是保存在 CE 以及内存中。

代码

工作流定义被转移至 PE 中之后,可以用 PE API 来访问它,代码如下。

清单 7. 打印工作流定义
 public void testPrintTransferredWorkflowDefinition() throws VWException { 
 String workClassName = "SampleParticipantFlow"; 
 VWWorkflowDefinition workflowDef = vwSession.fetchWorkflowDefinition( 
	 -1, workClassName, true); 
 VWMapDefinition[] maps = workflowDef.getMaps(); 
 for (int i = 0; i < maps.length; i++) { 
	 VWMapDefinition map = maps[i]; 
	 System.out.println("\t***********************************"); 
  System.out.println("\tMap Name: " + map.getName()); 
 System.out.println("\tMap ID: " + map.getMapId()); 
 VWMapNode[] steps = map.getSteps(); 
 for (int j = 0; j < steps.length; j++) { VWMapNode step = steps[j]; 
 System.out.println("\t\tStep Name: " + step.getName()); 
 System.out.println("\t\tStep ID: " + step.getStepId()); } } 
 } 

 ******************************************************* 
 Map Name: Malfunction Map ID: -4 Step Name: StartStep Step ID: 0 
 Step Name: Review Step ID: 1 Step Name: Return Step ID: 3 
 ******************************************************* 
 Map Name: Terminate Map ID: -3 Step Name: StartStep Step ID: 0 
 ******************************************************* 
 Map Name: Workflow Map ID: -2 Step Name: LaunchStep 
 Step ID: 0 Step Name: ParticipantStep Step ID: 3

您还可以通过调用 VWWorkflowDefinition 的 AsXMLString 方法得到工作流定义的完整 XML 描述。

正在运行的流程实例的历史信息

工作区操作

您需要打开流程管理器或流程跟踪器来查看正在运行(还未结束)的工作流实例的历史信息,由于流程管理器和流程跟踪器相对比较复杂,这里就不详述了,您可以参考 FileNet P8 平台文档。

数据库

您可以查看 VWLog 表中的数据。

代码

清单 8. 查看 SampleParticipantFlow 流程实例主图的历史
 public void testShowWorkflowInstanceHistory() throws VWException { 
 String workflowNumber = "59304C5DFA7D2A47A621C41A6BE08AF0"; 
 // number of SampleParticipantFlow ’ s instance 
 int mapId = -2; // id of the main map - Workflow 
 // query all work objects and find the root work object and get corrsponding process 
 VWRoster vwRoster = vwSession.getRoster( "DefaultRoster" ); 
 VWRosterQuery rQuery = vwRoster.createQuery( 
 null, null, null, VWRoster.QUERY_NO_OPTIONS, null, null, 
 VWFetchType.FETCH_TYPE_WORKOBJECT); 
 VWProcess process = null; while(rQuery.hasNext()) { 
 VWWorkObject workObject = (VWWorkObject) rQuery.next(); 
 if (workflowNumber.equals(workObject.getWorkObjectNumber())) 
 { process = workObject.fetchProcess(); } } 
 // print workflow instance history 
 if (process != null) { 
 VWWorkflowHistory wflHistory = process.fetchWorkflowHistory(mapId); 
 System.out.println("\t*****************************************************"); 
 while( wflHistory.hasNext() ) { 
 VWStepHistory stepHistory = wflHistory.next(); 
 System.out.println( "\tStep Id: " + stepHistory.getStepId() ); 
 System.out.println( "\tStep Name: " + stepHistory.getStepName() ); 
 stepHistory.resetFetch(); 
 while( stepHistory.hasNext() ) { 
 VWStepOccurrenceHistory stepOccHistory = stepHistory.next(); 
 System.out.println( "\tStep Occurrence History: " ); 
 System.out.println( "\t\tStep Occurrence Id: " + stepOccHistory.getOccurrenceId() ); 
 while (stepOccHistory.hasNext()) { 
 VWStepWorkObjectHistory stepWoHistory = stepOccHistory.next(); 
 System.out.println("\t\tStep Work Object History: "); 
 System.out.println("\t\t\tWork Object Number: " + stepWoHistory.getWorkObjectNumber()); 
 System.out.println("\t\t\tIs Completed: " + stepWoHistory.getIsCompleted()); } 
 } } } } 
 ***************************************************** 
 Step Id: 0 Step Name: LaunchStep Step Occurrence History: 
 Step Occurrence Id: 1223475598 Step Work Object History: 
 Work Object Number: 59304C5DFA7D2A47A621C41A6BE08AF0 Is 
 Completed: true Step Id: 3 Step Name: ParticipantStep Step Occurrence 
 History: Step Occurrence Id: 1223475599 Step Work Object History: 
 Work Object Number: FE20BFB3C16A964981B7270D8A1CB4CA Is 
 Completed: false Step Work Object History: Work Object Number: 
 4F9A0983DDDC6B438EEC6DF1D40FC203 Is Completed: false 
 Step Work Object History: Work Object 
 Number: 2CA9351E1819C34480A59DF3BF548DD0 Is Completed: false

相关 Java 类简介(对 PE API Java 文档的补充):

  • VWProcess – 用于访问运行中的工作流实例的信息,如状态,活动工作项,历史信息等。
  • VWWorkflowHistory – 用于访问一个正在运行的工作流实例的某个图 (Map) 的历史信息。
  • VWStepHistory – 零或多个 VWStepHistory 实例可以从一个 VWWorkflowHistory 实例得到。一个 VWStepHistory 实例用于访问一个工作流实例的某个节点的历史信息。
  • VWStepOccurrenceHistory – 零或多个 VWStepOccurrenceHistory 实例可以从一个 VWStepHistory 实例得到。一个 VWStepOccurrenceHistory 实例用于访问一个工作流节点的一次发生 (occurrence),这个节点可能已经完成了,也可能正在运行。一次发生意味着工作流实例运行到达该节点一次。当发生完成时,工作流实例继续向下一个节点前进。
  • VWStepWorkObjectHistory – 零或多个 VWStepWorkObjectHistory 实例可以从一个 VWStepOccurrenceHistory 实例得到。一个 VWStepWorkObjectHistory 实例用于访问一个相应节点产生的工作项,这个工作项可能已经完成,也可能正在等待处理。
  • VWParticipantHistory – 零或多个 VWParticipantHistory 实例可以从一个 VWStepWorkObjectHistory 实例得到。一个 VWParticipantHistory 实例用于访问一个参与者 (participant) 在相应工作项上的活动。一个工作项可能有多位用户先后参与编辑和完成,例如在它被重新分配,甚至多重重新分配的情况下。

工作流事件日志 (Event Log)

工作区操作

您需要打开流程管理器来查询工作流实例在 PE 中的事件日志,这个工作流实例可以是正在运行的,也可以是已经结束了的。关于流程管理器中的操作,您可以参考 FileNet P8 平台文档。

数据库

您可以查看 VWLog 表中的数据。

代码

清单 9. 查看流程实例的事件日志
 public void testShowWorkflowInstanceEventLog() throws VWException { 
 String workflowNumber = "59304C5DFA7D2A47A621C41A6BE08AF0"; 
 VWLog vwLog = vwSession.fetchEventLog("DefaultEventLog"); 
 String filter = null; 
 Object[] substitutionVars = null; 
 VWLogQuery vwLogQuery = vwLog.startQuery( 
	 null, null, null, VWLog.QUERY_NO_OPTIONS, filter, substitutionVars); 
 while (vwLogQuery.hasNext()) { 
	 VWLogElement vwLogElement = vwLogQuery.next(); 
	 if (workflowNumber.equals(vwLogElement.getWorkFlowNumber())) { 
	 printLogElement(vwLogElement); 
	 } 
 } 
 } 

 private void printLogElement(VWLogElement vwLogElement) throws VWException { 
 System.out.println("\t***************************"); 
 System.out.println("\tEvent Type: " + 
     VWLoggingOptionType.getLocalizedString(vwLogElement.getEventType())); 
 System.out.println("\tUser Name: " + " " + vwLogElement.getUserName()); 
 System.out.println("\tMap Name: " + vwLogElement.getMapName()); 
 System.out.println("\tStep Name: " + vwLogElement.getStepName()); 
 System.out.println("\tQueue Name: " + vwLogElement.getQueueName()); 
 System.out.println("\tSubject Name: " + vwLogElement.getSubject()); 
 System.out.println("\tTimestamp: " + vwLogElement.getTimeStamp()); 
 System.out.print("\tAll Data Fields: "); 
 printDataFields(vwLogElement.getDataFields()); 
 } 
 ********************************************* 
 Event Type: WOParentCreation User Name: administrator 
 Map Name: Workflow Step Name: LaunchStep Queue Name: null 
 Subject Name: SampleParticipantFlowInstance1 
 Timestamp: Wed Oct 08 22:19:58 CST 2008 
 All Data Fields: F_WobNum=59304C5DFA7D2A47A621C41A6BE08AF0, 
 F_WorkSpaceId=241, F_OperationId=-1, F_InstrSheetId=-2, F_WorkOrderId=0, 
 F_ParentWobNum=00000000000000000000000000000000, F_Tag=*, 
 F_WorkClassId=15, F_WPClassId=-1, F_TimeStamp=Wed Oct 08 22:19:58 CST 2008, 
 F_SeqNumber=15937, F_UserId=50, F_BoundUserId=0, F_MachineId=-2, 
 F_EventType=140, F_Duration=0, F_OccurrenceId=1223475598, F_Text=, 
 F_WCRevision=1, F_ServerSeqNum=1, F_Originator=50, 
 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, 
 F_Comment=, F_Response=, F_Subject=SampleParticipantFlowInstance1, 
 F_TrackerStatus=0, F_UniqueId=0.0, F_StartTime=Wed Oct 08 22:19:58 CST 2008, 
 F_EnqueueTime=Fri Aug 17 04:32:32 CST 1906, F_WFDeadline=0, 

 ********************************************* 
 Event Type: WOEmptyStepMsg User Name: administrator 
 Map Name: Workflow Step Name: LaunchStep 
 Queue Name: null Subject Name: SampleParticipantFlowInstance1 
 Timestamp: Wed Oct 08 22:19:58 CST 2008 
 All Data Fields: F_WobNum=59304C5DFA7D2A47A621C41A6BE08AF0, 
 F_WorkSpaceId=241, F_OperationId=-1, F_InstrSheetId=-2, F_WorkOrderId=0, 
 F_ParentWobNum=00000000000000000000000000000000, F_Tag=*, 
 F_WorkClassId=15, F_WPClassId=-1, F_TimeStamp=Wed Oct 08 22:19:58 CST 2008, 
 F_SeqNumber=15938, F_UserId=50, F_BoundUserId=0, F_MachineId=-2, 
 F_EventType=500, F_Duration=0, F_OccurrenceId=1223475598, F_Text=, 
 F_WCRevision=1, F_ServerSeqNum=1, F_Originator=50, 
 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Comment=, 
 F_Response=, F_Subject=SampleParticipantFlowInstance1, F_TrackerStatus=0, 
 F_UniqueId=0.0, F_StartTime=Wed Oct 08 22:19:58 CST 2008, 
 F_EnqueueTime=Fri Aug 17 04:32:32 CST 1906, F_WFDeadline=0, 

 ********************************************* 
 Event Type: WOChildCreation User Name: administrator 
 Map Name: Workflow Step Name: ParticipantStep 
 Queue Name: Inbox Subject Name: SampleParticipantFlowInstance1 
 Timestamp: Wed Oct 08 22:19:58 CST 2008 
 All Data Fields: F_WobNum=FE20BFB3C16A964981B7270D8A1CB4CA, 
 F_WorkSpaceId=241, F_OperationId=-1, F_InstrSheetId=-2, F_WorkOrderId=3, 
 F_ParentWobNum=59304C5DFA7D2A47A621C41A6BE08AF0, F_Tag=*, 
 F_WorkClassId=15, F_WPClassId=1, F_TimeStamp=Wed Oct 08 22:19:58 CST 2008, 
 F_SeqNumber=15939, F_UserId=50, F_BoundUserId=0, F_MachineId=-2, 
 F_EventType=130, F_Duration=0, F_OccurrenceId=1223475599, F_Text=, 
 F_WCRevision=1, F_ServerSeqNum=1, F_Originator=50, 
 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Comment=, 
 F_Response=, F_Subject=SampleParticipantFlowInstance1, F_TrackerStatus=0, 
 F_UniqueId=0.0, F_StartTime=Wed Oct 08 22:19:58 CST 2008, 
 F_EnqueueTime=Fri Aug 17 04:32:32 CST 1906, F_WFDeadline=0, 

 ********************************************* 
 Event Type: WPWorkObjectQueued User Name: administrator 
 Map Name: Workflow Step Name: ParticipantStep 
 Queue Name: Inbox Subject Name: SampleParticipantFlowInstance1 
 Timestamp: Wed Oct 08 22:19:58 CST 2008 All Data Fields: 
 F_WobNum=FE20BFB3C16A964981B7270D8A1CB4CA, F_WorkSpaceId=241, 
 F_OperationId=-1, F_InstrSheetId=-2, F_WorkOrderId=3, 
 F_ParentWobNum=59304C5DFA7D2A47A621C41A6BE08AF0, F_Tag=*, 
 F_WorkClassId=15, F_WPClassId=1, 
 F_TimeStamp=Wed Oct 08 22:19:58 CST 2008, F_SeqNumber=15940, 
 F_UserId=50, F_BoundUserId=256, F_MachineId=-2, F_EventType=352, 
 F_Duration=0, F_OccurrenceId=1223475599, F_Text=, F_WCRevision=1, 
 F_ServerSeqNum=1, F_Originator=50, 
 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Comment=, 
 F_Response=, F_Subject=SampleParticipantFlowInstance1, F_TrackerStatus=0, 
 F_UniqueId=746.0, F_StartTime=Wed Oct 08 22:19:58 CST 2008, 
 F_EnqueueTime=Fri Aug 17 04:32:32 CST 1906, F_WFDeadline=0, 

 ********************************************* 
 Event Type: WOChildCreation User Name: administrator 
 Map Name: Workflow Step Name: ParticipantStep 
 Queue Name: Inbox Subject Name: SampleParticipantFlowInstance1 
 Timestamp: Wed Oct 08 22:19:58 CST 2008 
 All Data Fields: F_WobNum=4F9A0983DDDC6B438EEC6DF1D40FC203, 
 F_WorkSpaceId=241, F_OperationId=-1, F_InstrSheetId=-2, F_WorkOrderId=3, 
 F_ParentWobNum=59304C5DFA7D2A47A621C41A6BE08AF0, F_Tag=*, 
 F_WorkClassId=15, F_WPClassId=1, F_TimeStamp=Wed Oct 08 22:19:58 CST 2008, 
 F_SeqNumber=15941, F_UserId=50, F_BoundUserId=0, F_MachineId=-2, 
 F_EventType=130, F_Duration=0, F_OccurrenceId=1223475599, F_Text=, 
 F_WCRevision=1, F_ServerSeqNum=1, F_Originator=50, 
 F_WorkFlowNumber=59304C5DFA7D2A47A621C41A6BE08AF0, F_Comment=, 
 F_Response=, F_Subject=SampleParticipantFlowInstance1, F_TrackerStatus=0, 
 F_UniqueId=0.0, F_StartTime=Wed Oct 08 22:19:58 CST 2008, 
 F_EnqueueTime=Fri Aug 17 04:32:32 CST 1906, F_WFDeadline=0,

这里输出太长,截取了前一部分。

关于事件类型 (Event Type) 的解释,您可以参考 VWLoggingOptionType 类的 Java 文档。

总结

本文讲述了 FileNet 工作流在 PE 中的基本生命周期以及相应的用于观察和管理它的 PE API 。相信您在看完本文后会对 FileNet 工作流在 PE 中的运行过程和相应的底层细节有基本的了解,同时能够开始开发为用户定制的工作流管理程序。

声明

本文仅代表作者的个人观点,不代表 IBM 的立场。


下载资源


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Information Management
ArticleID=369335
ArticleTitle=FileNet P8 工作流生命周期管理和 Process Engine API 应用介绍
publish-date=09162010