Integrate FileNet BPM with IBM Content Manager, Part 2: Implement the Java Business Entities and the gateway class for data in IBM Content Manager repository

An example using the "ABC Company" scenario

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.

Share:

S. H. Liu (shliu@tw.ibm.com), Advisory Software Engineer, IBM Japan

S. H. LiuS.H. Liu is an advisory software engineer in IBM China Software Development Lab (CSDL).



Dao-Quynh Dang (quynhdang@us.ibm.com), Software Engineer, IBM

Dao-Quynh Dang photoQuynh Dang is a senior software engineer in IBM IM Enterprise Content Management.



Peng Shi (shipeng@cn.ibm.com), Software Engineer, IBM Content Manager Development, IBM Japan

Peng ShiPeng 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.



03 April 2008

Also available in Vietnamese

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
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
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
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

DescriptionNameSize
Java Business Entities project for eclipseBO.zip10MB

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

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Information management on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Information Management
ArticleID=299298
ArticleTitle=Integrate FileNet BPM with IBM Content Manager, Part 2: Implement the Java Business Entities and the gateway class for data in IBM Content Manager repository
publish-date=04032008