FileNet Content Document PE流程开发

转载于http://www.ibm.com/developerworks/cn/data/library/techarticles/dm-0812liuwei/index.html

用例说明

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


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 ”节点,需要做的工作:

  1. 使用 PE API 从当前流程中获取 Attachment 对象
  2. 通过 Attachment 对象从 FileNet CE 中获取对应的 Document 对象
  3. 通过 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 中。程序中所需要做的工作:

  1. 获取 Document 对象(同上)
  2. 更新当前的 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);

猜你喜欢

转载自cl315917525.iteye.com/blog/1485824