您的位置:首页 > 其它

使用 FileNet Content API 开发以内容为核心的流程

2011-11-29 11:01 417 查看
前言

IBM FileNet P8 4.0 Platform 是一个以内容为核心的 BPM 产品,主要应用在金融行业,为企业提供流程管理和内容管理的相关服务。 FileNet BPM 在整个业务活动中通过对工作流程进行简化、自动化和优化来控制工作的流程。在处理大多数复杂的业务流程时 ( 包括数百万事务、数以千计的用户及众多的业务应用 ),FileNet BPM 具有足够的灵活性和扩展性。 BPM 帮助企业缩短流程的周期,自动地管理流程异常,因此企业可以立即响应内部事件和客户请求。功能强大的同时,也很易于使用、管理和部署。它强调“以人为本”的思想,从系统架构、流程建模和
API 上都体现出对人工活动良好的支持,因此适用于人工较多的长流程。

在 FileNet BPM 产品中,最核心的组件是:Process Engine 和 Content Engine 。 PE 提供了流程的运行和管理功能,是一个高效的工作流引擎。 CE 是负责内容管理的核心解决方案,它为结构化数据、半结构化数据和非结构化数据进行统一集中式管理,具体的功能有:内容的搜索与存储、版本管理、文档的生命周期管理、事件订阅等。本文主要介绍使用 CE API 进行内容存储和管理,并结合 PE 实现流程中内容的共享。

回页首

用例说明

本文样例是基于企业内部的文档管理流程的一个片断。在该流程中,秘书可以上传和更新某些文档资料;公司的管理者可以检查上传的文件;上述三个活动,代表了对文档的创建、查询和更新操作,文档被存储到 FileNet Ce 中,并通过 PE 的“引用”,可以被流程中每个任务活动所共享。

图 1. 用例图



回页首

Content Engine API 使用介绍

1 . CE 连接获取

在操作 CE 之前,需要获取与 CE 的连接。 FileNet 提供了两种连接方式:EJB transport 和 Web services transport 。如果,使用 EJB transport 连接 CE,所必需的 JAAS context 常常已经建立 (例如:如果使用的应用服务器是 Websphere Application Server, 可以配置相关的 JAAS), 因此不需要使用代码建立 JAAS context:

清单 1. 获取 CE connection

// Need setup parameters of JVM to login; parameters include  url and jaas config
// … …
// Get the connection
String uri = "http://CEServer:9080/wsi/FNCEWS40DIME/";
Connection conn = Factory.Connection.getConnection(uri);
// Get the default domain
Domain domain = Factory.Domain.getInstance(conn, null);
// Get an object store
ObjectStore os = Factory.ObjectStore.fetchInstance(domain,
"ObjectStoreName", null);

如果使用一般的 JAVA 应用程序或者 Web services transport 连接 CE,需要额外增加下列方法建立一个 JAAS context:

清单 2. 创建用户上下文

// conn: CE connection;
Subject subject = UserContext.createSubject(conn, user, password, null);
UserContext uc = UserContext.get();
uc.pushSubject(subject);

当释放 CE 的联接,需要使用“ UserContext.get().popSubject() ”,将当前登录用户的主题对象从用户上下文中清除掉;否则,如果另外用户登陆到 PE 和 CE 中,进行相应的操作,可能会出现下列异常:

清单 3. 异常信息

[Err=d56d0044] Security attributes disallow access
at filenet.pe.peorb.client.ORBUtility.mapServerException(ORBUtility.java:370)
at filenet.pe.peorb.client.ORBSession.executeRPC(ORBSession.java:1203)
at filenet.pe.peorb.client.ORBSession.getQueueNames(ORBSession.java:1788)
at filenet.vw.api.VWSession.getQueue(VWSession.java:1120)

2 .基本操作

下面将介绍使用 CE API 对文档进行存储和管理。

获取一个 Object Store 对象

Object Store 是一个独立的、存在于 Domain 的对象。它提供了对资源的访问和存取,这里的资源包括 documents,folders, custom objects 等,以及有关这些资源的元数据(Class)。 Object Store 代表了这些资源在 CE 上的存储位置。借助 Object Store 对象提供的方法,开发者可以对 Content Engine Server 中的资源进行操作。

清单 4. 获取 Object Store 对象

Domain domain = Factory.Domain.getInstance(conn, null);
ObjectStore os = Factory.ObjectStore.fetchInstance(domain, objStoreName, null);
return os;

清单 5. 获取一个 Folder 对象

Folder folder = Factory.Folder.fetchInstance(objStore, folderPath, null);
return folder;

清单 6. 创建一个 Folder 对象

// os: objectStore; path: the parent folder in the objectStore
Folder folder = Factory.Folder.createInstance(os, path);
return folder;

清单 7. 通过 Class 的名字创建一个 Document 对象

Document myDoc = null;
myDoc = (Document) os.createObject(className);
// add some values for the properties of document
// ... ...
// add some external files for document
// ... ...
myDoc.checkin(AutoClassify.AUTO_CLASSIFY, CheckinType.MAJOR_VERSION );
myDoc.save(RefreshMode.REFRESH);
ReferentialContainmentRelationship rel = folder.file(myDoc,
AutoUniqueName.AUTO_UNIQUE, null,
DefineSecurityParentage.DEFINE_SECURITY_PARENTAGE);
rel.save(RefreshMode.NO_REFRESH);
//return myDoc;

1 .当创建一个 document 对象时,可以为它的属性对象赋值。

清单 8. 创建 Document 对象定义属性

// … …
//'docProps' is 'java.util.Properties' object for input
com.filenet.api.property.Properties properties = myDoc.getProperties();
for (Iterator iterator = docProps.keySet().iterator(); iterator.hasNext();)
{
String key = (String) iterator.next();
String value = docProps.getProperty(key);
properties.putValue(key, value);
}
// … …

当 document 对象中的一个属性的类型不是简单类型,而是指向另外一个对象时,需要建立相互之间的引用关系。首先,使用 Enterprise Manager 在 CE 中创建 document class 过程中,为两个 class 之间的相互关系创建一种特殊的属性:association property 。使用它可以在 design time 为两个 class 建立引用关系,当 class 在 runtime 被实例化为对象,相关的引用使用下列代码实现: 

(1)当对象之间是 1:1 的关系时,需要在对象双方建立关系。

清单 9. 创建 Document 对象之间的关系

//create the association between 'doc' and 'itemDoc' documents
com.filenet.api.core.Document doc = ...;
com.filenet.api.core.Document itemDoc = ...;
com.filenet.api.property.Properties a_properties = doc.getProperties();
a_properties.putObjectValue("association name", itemDoc);
com.filenet.api.property.Properties b_properties = itemDoc.getProperties();
b_properties.putObjectValue("association name", doc);

(2)当对象之间是 1:* 的关系时,只需在“ * ”的一方对象中分别建立关系,而 CE 会自动在“ 1 ”的一方创建引用。

清单 10. 创建 Document 对象之间的关系

//create the association between 'doc' and 'itemDoc' documents
com.filenet.api.core.Document doc = ...;
com.filenet.api.core.Document itemDoc1 = ...;
com.filenet.api.core.Document itemDoc2 = ...;
// … …
com.filenet.api.property.Properties properties1 = itemDoc1.getProperties();
com.filenet.api.property.Properties properties2 = itemDoc2.getProperties();
// … …
properties1.putObjectValue("association name", doc);
properties2.putObjectValue("association name", doc);
// … …

2 .可以为创建的 document 对象增加相关的外部文件,使用“ ContentElementList ”存储文件流对象。

清单 11. 创建 ContentElementList 对象

myDoc = (Document) os.createObject(className);
ContentElementList contentList = Factory.ContentElement.createList();
for (int i = 0; i < files.length; i++) {
ContentTransfer content = Factory.ContentTransfer.createInstance();
content.setCaptureSource(new FileInputStream(filePath);
contentList.add(content);
}
myDoc.set_ContentElements(contentList);

搜索CE中的一个对象

可以按照 Document Class 的名字在 Object Store 中搜索相关的对象:

清单 12. 搜索对象

//queryStr: SELECT * FROM ClassName
SearchSQL sqlObject = new SearchSQL(queryStr);
SearchScope searchScope = new SearchScope(os);
RepositoryRowSet rowSet = searchScope.fetchRows(sqlObject, null, null,
new Boolean(true));
for (Iterator iterator = rowSet.iterator(); iterator.hasNext();) {
RepositoryRow row = (RepositoryRow) iterator.next();
Properties props = row.getProperties();
for (Iterator iterator2 = props.iterator(); iterator2.hasNext();) {
Object o = (Object) iterator2.next();
System.out.println(o);
}

回页首

实现细节

下面将介绍使用上述 CE API,并结合 FileNet PE,在一个文档管理流程中实现内容的共享。

流程创建

使用 FileNet Process Designer 设计一个 DocumentManager 流程,并为流程创建一个名为“ DocAttachmentID ”的“ Attachment ”变量,在后面的开发实践中,它将指向一个在 CE 中创建好的 document 实例,用于存放上传的文件。下图描述了这个流程的片断:

图 2. 文档管理流程片断



定义“创建文档”

这一步对应流程中的“ Upload Documents ”节点,需要做的工作:上传一些文件,并把它们存放到 FileNet CE 中。

首先为当前的文档管理流程分配一个业务 ID,唯一标识一个流程实例。同时,使用 CE API 在指定的目录下创建一个 Folder,名字为业务 ID,表示对于当前的流程,相关的文档都存放在这个 Folder 中。然后,在这个 Folder 下创建一个 document 对象,所有上传的文件都存放到该对象的“ ContentElementList ”中。最后将当前创建好的 document 对象与流程的 attachment 对象“ DocAttachmentID ”建立关联,代码如下:

清单 13. 创建 Attachment 对象

VWAttachment vwattach = new VWAttachment();
vwattach.setId(document.get_Id().toString());
vwattach.setVersion(document.get_VersionSeries().get_Id().toString());
vwattach.setLibraryName(objStoreName);
vwattach.setLibraryType(VWLibraryType.LIBRARY_TYPE_CONTENT_ENGINE);
vwattach.setType(VWAttachmentType.ATTACHMENT_TYPE_DOCUMENT);
vwStepElement.setParameterValue("ClaimDocID", vwattach, false);

其中,“ vwStepElement ”对象表示活动“ Upload Document ”的实例,可以通过 FileNet PE API 获取。当建立好与流程中 Attachment 对象的关联后,流程的其他活动实例,可以通过 Attachment 对象从 CE 中获取对应的 document 。需要说明的是,因为 FileNet PE API 和 CE API 是彼此独立的,它们之间是不能通过“对象引用”的方式直接交互,即不能在 PE 中保留一个对 CE 的对象引用,只能保留简单类型的值(String, int
等)。因此,建立两者之间的联系只是把当前 CE 中 document 实例的 ID(String),关联到 PE 中 Attachment 对象的 ID(String)。

定义“查询文档”

这一步对应流程中“ Review Documents ”节点,需要做的工作:

使用 PE API 从当前流程中获取 Attachment 对象

通过 Attachment 对象从 FileNet CE 中获取对应的 Document 对象

通过 Document 对象的“ ContentElementList ”,得到所有上传的文件流对象,代码如下:

清单 14. 获取 Attachment 对象

// get attachment object from process
VWAttachment vwattach = (VWAttachment) stepElement.getParameterValue
("DocAttachmentID");
// retrieve document object from CE;
Document doc = Factory.Document.fetchInstance(os, vwattach.getId(),
null);
ContentElementList list = claimDoc.get_ContentElements();
ContentTransfer content = (ContentTransfer) list.get(i);
InputStream is = content.accessContentStream();
String mimeType = content.get_ContentType();

定义“更新文档”

这一步对应流程中“ Add Additional Documents ”节点。根据业务场景,当用户上传的文件不充分时,流程转向该任务节点,允许用户(secretary)提交额外的文件到 FileNet CE 中。程序中所需要做的工作:

获取 Document 对象(同上)

更新当前的 Document 对象,增加新的文件。 FileNet 使用“ Reservation ”实现文档的更新,被更新后的文档是一个新的对象,版本自动会增加,原有版本的对象会继续保留。因此,对于同一个业务对象,根据版本的多少,可以同时存在多个 document 实例。在 FileNet Workplace 中,只显示最新版本的文档对象,如果需要显示所有版本里面的内容,需要通过程序得到对应版本的全部对象。

清单 15. 更新 Document 对象

claimDoc.checkout(ReservationType.EXCLUSIVE, null, null,null);
claimDoc.save(RefreshMode.NO_REFRESH);
Document reservation = (Document) claimDoc.get_Reservation();
ContentElementList contentList = reservation.get_ContentElements();
ContentTransfer content = Factory.ContentTransfer.createInstance();
content.setCaptureSource(...);
contentList.add(content);
reservation.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY,CheckinType.MAJOR_VERSION);
reservation.save(RefreshMode.REFRESH);
claimDoc.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY,CheckinType.MAJOR_VERSION);

回页首

结论

本文深入介绍了 FileNet CE API 的使用,并结合 FileNet PE API 详细说明了如何在流程中访问 CE,实现内容共享。本文选取的业务场景和程序样例,可作为使用 FileNet BPM 产品开发一个以内容为中心的生产流程的实践。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐