 | Level: Introductory S. H. Liu (shliu@tw.ibm.com), Advisory Software Engineer, IBM Japan Dao-Quynh Dang (quynhdang@us.ibm.com), Software Engineer, IBM
Peng Shi (shipeng@cn.ibm.com), Software Engineer, IBM Content Manager Development, IBM Japan
03 Apr 2008 This is the second in a series of four articles that show you how to
integrate FileNet® Business Process Management with IBM® DB2 ® Content
Manager Version 8. In this article, learn about the work performers in FileNet P8,
implement the Java™ business entities and create a Java gateway class. Also,
see how to use Java serialization to circumvent certain limitations.
Introduction
Part 1 of this series introduced you to the FileNet P8 BPM and IBM Content Manager architectures. The article used a fictitious ABC Company's Auto Insurance Claim system to show you how to integrate these two powerful products.
Part 2 introduces the FileNet P8 work performers and shows you how to implement the Java business entities. You will learn to create a Java gateway class and see how to use Java serialization to circumvent certain limitations.
Work performers
In order to use a third party content repository, FileNet Business Process Management
(BPM) needs the capability to communicate with the IBM Content Manager repository. FileNet work performers can enable BPM to interact with third party codes or applications.
In FileNet P8, work performers enable an application to perform an operation or a set of
operations associated with a workflow. Typically, work performers are designed without a
user interface and are used to perform automatic workflow operations, such as those
associated with a specific step in a workflow definition. Work performer operations
associated with workflow steps include logging in and establishing a process engine
session, polling a user queue or system queue (attempting to find operations related to a
particular workflow step), locking the retrieved object, processing the work (data update
and so on), and cycling back to queue polling. Simply put, work performers are needed to interact with third party applications.
There are two types of work performers, component integrator-based and daemon-based. The
component integrator-based performer is adopted in this example.
The component integrator-based work performer is a component implemented as either a Java
class or Java Messaging Service (JMS) event. A Java component can be used to perform all
operations associated with a workflow. Figure 1 illustrates the component integrator architecture:
Figure 1. FileNet P8 component
integrator architecture
The Java or JMS component can be managed by the component manager. The component manager
configures and communicates with service adapters. At runtime, the component manager polls
component queues for work items that request JMS or processing by Java components, and
connects a work item requesting a component to the appropriate service adapter. The Java
adapter handles process calls to Java objects, which are represented to the process engine
as operations on queues (work items) where each operation is done by a method of the Java
class. The Java adapter executes the interface to the Java component, then automatically
waits for a response from this component, updates the work item, and dispatches this work
item to the next workflow step. The JMS adapter places messages on the JMS Queue and dispatches the associated work item. The JMS adapter handles posting of process events to a message queue (in the form of an XML event based on the step element for the given operation).
 |
Implement the Java business entities for the ABC Company
The ABC Company wants to store all the content data in the existing IBM Content Manager. And
it also wants to use FileNet BPM to build a process centric application. So you need to
implement work performers in BPM in order to manipulate the content in the existing IBM Content Manager.
You may encapsulate the third party application logic and expose the interface when
implementing the Java component. For ABC Company's case, you first implement the Java
business entities which can access the data in the IBM Content Manger. Figure 2 shows the
Java business entities architecture:
Figure 2. Java business entities architecture
As the architecture shows, you can create the data transfer object (DTO) and the data
access object (DAO) which are corresponding to each class in the class diagram (Part
1; Figure 4). Taking class "AutoClaim" as an example, we've created a DTO class AutoClaim.java and a DAO class AutoClaimDAO.java.
The following Java code is AutoClaim.java. It contains the property definitions and
related getter and setter methods. It represents the data value for one item in the IBM Content Manager repository.
Listing 1. The sample DTO - AutoClaim.java
public class AutoClaim
{
public AutoClaim ()
{
}
private String claimID;
public String getClaimID()
{
return this.claimID;
}
public void setClaimID(String claimID)
{
this.claimID = claimID;
}
private Integer claimStatus;
public Integer getClaimStatus()
{
return this.claimStatus;
}
public void setClaimStatus(Integer claimStatus)
{
this.claimStatus = claimStatus;
}
private String openingDate;
public String getOpeningDate()
{
return this.openingDate;
}
public void setOpeningDate(String openingDate)
{
this.openingDate = openingDate;
}
private Integer claimAmount;
public Integer getClaimAmount() {
return claimAmount;
}
public void setClaimAmount(Integer claimAmount) {
this.claimAmount = claimAmount;
}
private String eventID;
public String getEventID() {
return this.eventID;
}
public void setEventID(String eventID) {
this.eventID = eventID;
}
private String pidString;
public String getPidString() {
return pidString;
}
public void setPidString(String pidString) {
this.pidString = pidString;
}
}
|
The following Java code is AutoClaimDAO.java which is a data access object. It contains
all the methods which call IBM Content Manager OOAPI to manipulate the data in the IBM Content Manager.
Listing 2. The sample DAO - AutoClaimDAO.java
public class AutoClaimDAO
{
private String itemType;
public AutoClaimDAO()
{
itemType = "AutoClaim";
}
public String create(AutoClaim autoClaim) throws DKException, Exception
{
String pidString = null;
DKDatastoreICM dsICM = SConnectDisconnectICM.connect();
DKDDO ddo = dsICM.createDDO("AutoClaim", DKConstant.DK_CM_ITEM);
setAttrToDDO(ddo, autoClaim);
ddo.add();
pidString = ddo.getPidObject().pidString();
dsICM.disconnect();
return pidString;
}
public AutoClaim retrieveAutoClaimByClaimID(String claimID)
throws DKUsageError, DKException, Exception
{
AutoClaim autoClaim = null;
String queryString = "/AutoClaim[@Claim=\""+claimID+"\"]";
DKDatastoreICM dsICM = SConnectDisconnectICM.connect();
dkIterator dkIter =
(dkIterator) SConnectDisconnectICM.search(dsICM, queryString, 0, true);
if(dkIter.more())
{
autoClaim = new AutoClaim();
DKDDO ddo = (DKDDO)dkIter.next();
ddo.retrieve(DKConstant.DK_CM_CONTENT_ITEMTREE +
DKConstant.DK_CM_CONTENT_NO);
setValueToAutoClaim(ddo, autoClaim);
autoClaim.setPidString( ddo.getPidObject().pidString() );
}
dsICM.disconnect();
return autoClaim;
}
public void update(String pidString, AutoClaim autoClaim)
throws DKUsageError, DKException, Exception
{
DKDatastoreICM dsICM = SConnectDisconnectICM.connect();
DKDDO ddo= dsICM.createDDO(pidString);
ddo.retrieve(DKConstant.DK_CM_CONTENT_ITEMTREE +
DKConstant.DK_CM_CONTENT_NO);
DKDatastoreExtICM ext = new DKDatastoreExtICM(dsICM);
if(!ext.isCheckedOut(ddo))
{
ext.checkOut(ddo);
}
setAttrToDDO(ddo, autoClaim);
dsICM.updateObject(ddo, DKConstant.DK_CM_CHECKIN);
dsICM.disconnect();
}
public void delete(String pidString) throws DKUsageError, DKException, Exception
{
DKDatastoreICM dsICM = SConnectDisconnectICM.connect();
DKDDO ddo = dsICM.createDDO(pidString);
ddo.del();
dsICM.disconnect();
}
public void setAttrToDDO(DKDDO ddo, AutoClaim autoClaim) throws DKUsageError
{
if(autoClaim.getClaimID()!=null)
ddo.setData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,"ClaimID"),
autoClaim.getClaimID());
if(autoClaim.getClaimStatus()!=null)
ddo.setData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,"ClaimStatus"),
autoClaim.getClaimStatus());
if(autoClaim.getOpeningDate()!=null)
ddo.setData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,"OpeningDate"),
autoClaim.getOpeningDate());
if(autoClaim.getClaimAmount()!=null)
ddo.setData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,"ClaimAmount"),
autoClaim.getClaimAmount());
if( autoClaim.getEventID() != null )
ddo.setData( ddo.dataId( DKConstant.DK_CM_NAMESPACE_ATTR, "EventID" ),
autoClaim.getEventID() );
}
public void setValueToAutoClaim(DKDDO ddo, AutoClaim autoClaim)
throws DKUsageError
{
Object attr = null;
attr = ddo.getData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
"ClaimID"));
if(attr!=null)
{
autoClaim.setClaimID((String)attr);
attr = null;
}
attr = ddo.getData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
"ClaimStatus"));
if(attr!=null)
{
autoClaim.setClaimStatus((Integer)attr);
attr = null;
}
attr = ddo.getData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
"OpeningDate"));
if(attr!=null)
{
autoClaim.setOpeningDate((String)attr);
attr = null;
}
attr = ddo.getData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
"ClaimAmount"));
if(attr!=null)
{
autoClaim.setClaimAmount((Integer)attr);
attr = null;
}
attr = ddo.getData(ddo.dataId(DKConstant.DK_CM_NAMESPACE_ATTR,
"EventID"));
if(attr!=null)
{
autoClaim.setEventID( (String) attr );
attr = null;
}
}
...
}
|
For other classes in the class diagram, there are similar Java classes such as AutoPolicy.java and AutoPolicyDAO.java.
You can download the Eclipse project which contains all these
Java class source code.
Implement the gateway class for the
Java business entities
Now you have got a set of Java business entities and also a lot of operation methods in
these entities. But in the FileNet Component Integrator, one component queue can only expose one Java class's methods. And you should conform to the following rules:
- The class must have a constructor without any parameters.
- The methods must be public.
- The methods can only contain allowable component operation parameter types. Refer to the component operation parameter types.
If you want to interact with the multiple Java classes from a third party application and
would like to register only one component queue for this application, you should wrap all
the Java classes' methods into one gateway class. Thus for ABC Company's Auto Insurance
Claim system, you should wrap all the DAO operation methods into one gateway class --
ICMOperation.java -- shown in the following Java code.
Listing 3. The sample wrapper class - ICMOperation.java
public class ICMOperation
{
public void createAutoClaim(String claimID,Integer claimStatus,
String openingDate,Integer claimAmount, String eventID) throws Exception
{
AutoClaim autoClaim = new AutoClaim();
autoClaim.setClaimID(claimID);
autoClaim.setClaimStatus(claimStatus);
autoClaim.setOpeningDate(openingDate);
autoClaim.setClaimAmount(claimAmount);
autoClaim.setEventID( eventID );
AutoClaimDAO dao = new AutoClaimDAO();
dao.create( autoClaim );
}
public Integer retrieveClaimStatusByClaimID(String claimID) throws Exception
{
AutoClaim autoClaim = getAutoClaim( claimID );
return autoClaim.getClaimStatus();
}
public void updateClaimStatusByClaimID( String claimID, Integer claimStatus )
throws Exception
{
AutoClaimDAO dao = new AutoClaimDAO();
AutoClaim autoClaim = dao.retrieveAutoClaimByClaimID( claimID );
autoClaim.setClaimStatus( claimStatus );
dao.update( autoClaim );
}
private AutoClaim getAutoClaim( String claimID ) throws Exception
{
return new AutoClaimDAO().retrieveAutoClaimByClaimID( claimID );
}
...
}
|
 |
A workaround using Java object parameters in Component Integrator
FileNet P8 Component Integrator only supports some primitive parameter types. But generally, some Java objects are always used as parameters
in an operation method. Here, we introduce a solution to overcome this limitation: Java serialization. Figure 3 shows this solution.
Figure 3. Java serialization solution
Using Java serialization, you can serialize the original Java object to a string in
memory. When you need to get the original Java object, you can deserialize the string to
the original Java object. Take AutoClaimDAO.java as an example.
If you want to use the DTO AutoClaim.java as the parameter
in the operation methods, you need to write two utility methods. One is to serialize the AutoClaim Java object to a string, while the other is to deserialize the string to the original AutoClaim Java object. The following Java code snippet shows these two methods.
Listing 4. The sample code of serialization and deserialization
public AutoClaim parseStringToAutoClaim( String autoClaimString )
throws IOException, ClassNotFoundException
{
ObjectInputStream objInput = null;
try
{
objInput = new ObjectInputStream( new ByteArrayInputStream(
new BASE64Decoder().decodeBuffer( autoClaimString ) ) );
return (AutoClaim) objInput.readObject();
}
finally
if( objInput != null )
{
objInput.close();
}
}
}
public String parseAutoClaimToString( AutoClaim autoClaim ) throws IOException
{
ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
ObjectOutputStream objOutput = null;
try
{
objOutput = new ObjectOutputStream( byteOutput );
objOutput.writeObject( autoClaim );
return new BASE64Encoder().encode( byteOutput.toByteArray() );
}
finally
{
byteOutput.close();
if( objOutput != null )
{
objOutput.close();
}
}
}
|
Then you should make AutoClaim serializable. The only thing needed is to let AutoClaim implement java.io.Serializable interface. The following code shows the serializable AutoClaim.
Listing 5. The sample code implements serializable
public class AutoClaim implements Serializable{
private static final long serialVersionUID = 4599855634813333505L;
...
} |
Now you can register the method which uses string to represent the Java object. And in the
client application, you should use the deserialization method to get the original Java
object. Take a look at the following code. We use a method in the registered class ICMOperation
to retrieve the AutoClaim Java object. After getting the
result, first use the serialization method to serialize the AutoClaim Java object to a string object, then return the string to a
client. Once the client gets the string, use the deserialization method to
deserialize the string to an AutoClaim object.
Listing 6. The sample code to walk around the parameter limitation
public String retrieveAutoClaimByClaimID( String claimID ) throws Exception
{
AutoClaim autoClaim = getAutoClaim( claimID );
return new AutoClaimDAO().parseAutoClaimToString( autoClaim );
}
|
Now we have Java business entities and a Java gateway class which expose all the operation
methods. You can download all these source codes in an Eclipse
Java project. Notice that the compiler compliance level should be set to 1.4 when
creating corresponding jar files due to the compatibility of the component integrator.
Conclusion
In Part 2 of this series, you have taken a look at the FileNet work performers and seen
the component integrator-based work performer in detail. You've created the Java business
entities and prepared a Java gateway class. We also introduced a solution to overcome the
FileNet component integrator's parameter limitation.
Part 3 describes how to implement the work performers for ABC Company's Auto Insurance Claim system.
Download | Description | Name | Size | Download method |
|---|
| Java Business Entities project for eclipse | BO.zip | 10MB | HTTP |
|---|
Resources Learn
Get products and technologies
- Download
FileNet Content Manager demo
to see how IBM FileNet P8 integrates content, process, and compliance to streamline, manage, and optimize an auto claim handling process.
- Download
IBM product evaluation versions
and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and
WebSphere®.
Discuss
About the authors  | 
|  | S.H. Liu is an advisory software engineer in IBM China Software Development Lab (CSDL). |
 | 
|  | Quynh Dang is a senior software engineer in IBM IM Enterprise Content Management. |
 | 
|  | Peng Shi is a software engineer in IBM China Software Development Lab (CSDL). He works on IBM Content Manager development. He is a certified WebSphere Studio V5.0 developer. He has also worked as software engineer for FileNet development. |
Rate this page
|  |