Integrating WebLogic Platform 8.1 with the Stellent Web Content Management System

by Munish Gandhi

Originally published on BEA Dev2Dev April 2005

Abstract

Integrating packaged applications with a J2EE application is a challenge developers face every day. This article provides an overview of integrating Stellent Web Content Management (WCM) with BEA WebLogic Platform 8.1. The author assumes that readers are familiar with the basics of content management systems and have some experience developing J2EE applications.

This article presents an overview of the integration layer exposed by Stellent. Different integration approaches are discussed and the relative advantages and drawbacks of these alternatives are provided. Although Stellent provides a rich assortment of integration options, recasting these as a BEA WebLogic Workshop control offers an alternative, simpler form of integration. This article show how we developed a WebLogic Workshop control based on the facade pattern, hiding the complexity of the Stellent API. The control implementation includes a set of JavaBean wrapper objects that encapsulate the input and output parameters required to access Stellent services such as checking in content and performing search operations. The control is available as a download.

Integration Architecture Overview

The Stellent Content Integration Suite (CIS) layer is a J2EE application deployment unit. The CIS application can be deployed on any WebLogic domain after making appropriate changes to the hosting domain (as per the CIS installation guide). The suite includes a web application with which developers can view and update the configuration options for the CIS and also view and execute available services like content search. Stellent provides a comprehensive Java API to invoke these services, allowing programs to access and manipulate content, workflows, and metadata, and run searches to retrieve content.

The Stellent command layer architecture consists of a set of command objects, driven by EJBs, that encapsulate distinct "commands" to the content server. These commands include common functions such as search, checkout, and workflow approval. Each command is tied to one or more Stellent service calls. The command layer is based on the J2EE command design pattern and is made up of three tiers:

  • Command Objects, which use Command EJBs
  • Command Facades/Invokers
  • Adapters based on EJB/JCA

This comprehensive array of integration options is depicted in Figure 1.

Stellent integration architecture
Figure 1. The Stellent integration architecture

The Command Facade/Invoker locates and instantiates a command by name. It executes a given command object and handles command execution (synchronously or asynchronously) based on command properties. The Command Facade/Invoker can be invoked locally or remotely, so you do not have to have the Stellent CIS deployed on the same system as your requesting application server. The Adapter Layer handles communication with the content server, encapsulates socket communication logic (opening, validating, and streaming bits through the socket), and implements the JCA CCI (Command Client Interface).

Integration options

Stellent offers a flexible and wide range of integration options. Each of these options have advantages and disadvantages:

  • Command Layer Integration
    The command layer integration is based on using the Stellent CIS client APIs to access specific services like checking in content. However, a developer must have an understanding of the Stellent API in terms of passing in parameters and retrieving results.

    Command layer integration presents the most flexible and extensible integration option. However, it requires more work at project start-up time. Using the proposed control should lessen the investment required to adopt this approach.

  • Content Portlet Suite - JSR 168-compliant
    The Stellent Content Portlet Suite solution, built on top of the CIS layer, provides access to Stellent Content Server, enabling users to update, search, and view content. The portlets can be enabled for different users based on their roles and permissions within the organization, and they can be customized for specific uses. Users can browse or search content based on their permissions, contribute new content (with the appropriate level of access), and view the progress of their content through workflow.

    Using the Content Portlet Suite presents an easy, out-of-the-box solution integration approach. However, these portlets aren't as customizable as using command layer integration. For example, it is not easy to build portlets that display a mix of metadata and document content. Additionally, these portlets do not support advanced functionality, like previewing content.

  • Content Management Service Provider Interface (SPI) implementation
    WebLogic Portal provides a Virtual Content Repository (VCR) that enables customers to plug in multiple, heterogeneous content repositories. Stellent has built an integration—or Content Service Provider implementation—that enables Stellent WCM to plug into the VCR. Stellent SPI integration for BEA is built on top of the CIS layer and is only compatible with BEA WebLogic Platform 8.1 Service Pack 2 and above.

    The SPI implementation enables the delivery of personalized content using the rich, content personalization JSP tags available with BEA WebLogic Portal. However, using the SPI is not as flexible and extensible as using the command-layer integration option.

These options are viable architecture approaches for integration. However, building a Stellent control provides significant additional benefits. A WebLogic WorkShop Java control provides enhanced ease of use. Developers can easily use the control to build front-end portal web applications consisting of page flows and portlets and also back-end integration applications made up of Web services and processes. Moreover, the control integrates well with WebLogic Workshop and other controls, and provides all the benefits that accrue from that. Java controls, therefore, provide a very flexible integration option.

The author has built a WebLogic Workshop control to access the most commonly used content management functions. The control provides a facade around the Stellent CIS APIs and uses JavaBean wrapper objects, which encapsulate results returned by invoking various Stellent services.

Stellent Control Overview

The control is designed to provide an easy-to-use wrapper and hides the complexity of the Stellent CIS APIs. Typically, the following code will need to be written to execute a Stellent search:

//Exception handling code not shown

//Get the command client

ICommandClient commandClient = new CommandClient();

commandClient.connect();

//Get the command facade

ICommandFacade commandFacade = 

        (ICommandFacade)commandClient.getBean(""CommandFacade"");

//Get the search command API object

ISCSSearchCommandAPI searchAPI = (ISCSSearchCommandAPI)

        (commandFacade).getCommandAPI ("search");

//Create Stellent ISCS context

ISCSContext context = commandFacade.createSCSContext();

//Set context properties - user, adapter, contextPath, locale, device

context.setUser("testUser"); 

LWDataBinder binder = searchAPI.search (context, "queryString", 25);

//Get the search resultset from binder

LWResultSet resultSet = binder.getResultSet("SearchResults");



//Iterate over data and do some operation

if (resultSet != null && !resultSet.isEmpty())

{

    resultSet.first();

    for (int i = 0; i < resultSet.getNumRows(); i++)

    {                

        int metadataCount = resultSet.getNumFields();

        for(int j = 0; j < metadataCount; j++){

            //Print the metadata name-value pair

            System.out.println(resultSet.getFieldName(j) + "="

                + resultSet.getStringValue(j));

        }

        resultSet.next();

    }

}

As you can see from this listing, accessing and using the API is straightforward if a little tedious. By encapsulating these operations as control methods, it is easier to interact with the CIS and you can build more composable code. Following this example, the control exposes the same code using the following control method:

StellentSearchResultSet search(StellentQueryBean queryBean)

Here StellentQueryBean and StellentSearchResultSet are JavaBean wrapper objects that encapsulate the input parameters that the method expects (user context, query string, and so on) and the results returned by invoking the search services respectively. Similar JavaBean objects have been used to encapsulate the input and output parameters required when invoking other Stellent services, thereby reducing complexity and providing developers with a much simpler interface to work with.

The control is built on top of the Stellent CIS layer and is organized under two components:

  1. Search Control: The following methods are provided for retrieving metadata and content:

    byte[] getFile(StellentUserContext userContext, String aDocId, 
    
             String aContent, String rendition) 
    
    byte[] getDynamicContent(StellentUserContext userContext, String aDocId, 
    
             String aContent, String rendition, boolean rewriteForDisplay) 
    
    StellentContentItem getDocInfoById(StellentUserContext userContext, String aDocId) 
    
    StellentContentItem getDocInfoByName(StellentUserContext userContext, String aDocName) 
    
    StellentSearchResultSet search(search.StellentQueryBean queryBean)
    
  2. Administration Control: The following methods are provided for managing content lifecycle and workflows:

    StellentWIPResultSet searchUnpublishedContent(StellentUserContext aUserContext) 
    
    void deleteContentByID(StellentUserContext aUserContext, String aDocId) 
    
    void newCheckIn(StellentUserContext aUserContext, String aContentId, 
    
             String aContentType, String aTitle, String aSecurityGroup, 
    
             String aSecurityAccount, Map aMetadataMap, InputStream aInpStream, 
    
             String aFileName, long aFileSize) 
    
    void revisionCheckIn(StellentUserContext aUserContext, String aDocId, 
    
             String aContentId, String aContentType, String aTitle, String aSecurityGroup, 
    
             String aSecurityAccount, String aRevisionLabel, Map aMetadataMap, 
    
             InputStream aInpStream, String aFileName, long aFileSize) 
    
    void checkout(StellentUserContext aUserContext, String aDocId, String aTitle) 
    
    void undoCheckout(StellentUserContext aUserContext, String aDocId) 
    
    void updateDocument(StellentUserContext aUserContext, String aDocId, String aContentID, 
    
             String aRevisionLabel, String aSecurityGroup, String aSecurityAccount, Map aFieldMap) 
    
    void approveWorkflow(StellentUserContext aUserContext, String aDocId) 
    
    void rejectWorkflow(StellentUserContext aUserContext, String aDocId, String aMessage)
    
    boolean isValidStellentUser(StellentUserContext aUserContext) 
    
    StellentWorkQueueResultSet getWorkflowQueueForUser(StellentUserContext aUserContext) 
    
    StellentDocInfoResultSet getDocInfoByID(StellentUserContext aUserContext, String aDocId)
    

Using the Stellent Control

The Stellent control encapsulates the Stellent API and exposes a pure Java interface for accessing the different content management interfaces mentioned above. The sample code below illustrates how to use the provided Stellent control to retrieve items from a user's pending workflow:

//Create new user context with the default adapter

StellentUserContext context = 

   new StellentUserContext("testUser");



try{

   StellentWorkQueueResultSet queueRS = 

      stellentAdmin.getWorkflowQueueForUser(context);   

   

   //do something with the retrieved results

   List list = queueRS.getResultBeans();

   

   for(int i=0;i<list.size();i++){

      StellentWorkQueueItem anItem = 

         (StellentWorkQueueItem)list.get(i);

      System.out.println(anItem.getTitle());

   }

}catch (StellentException se){

   //Exception handling code here

}

The Stellent control hides the complexity in connecting to Stellent and can be used in any WebLogic Workshop application from web applications and Web services to WebLogic Portal and WebLogic Integration applications. It provides significant productivity benefits and can be used across projects and development teams.

Lessons Learned

The biggest challenge the author faced in writing the JavaBean wrappers was interpreting the data in the databinder classes returned when invoking a Stellent service. Invoking any Stellent service returns a LWDataBinder object that consists of a set of name value pairs and a collection of one or many LWResultSet objects. The developed JavaBean wrapper objects StellentWIPResultSet, StellentWorkQueueResultSet, StellentDocInfoResultSet, StellentSearchResultSet, and StellentContentItem encapsulate this complexity and present the results returned by Stellent in a much simplified, easy-to-use way, thereby increasing developer productivity.

Conclusion

Stellent provides a wide range of options for integrating the Stellent Web Content Management system with WebLogic Platform 8.1. The J2EE-based Stellent CIS layer serves as the backbone for all these options. The JSR 168 portlets and the content management SPI implementation provide easy-to-use integration approaches that require minimal development effort. Command layer integration presents the most flexible and extensible integration option.

We have found that recasting the Stellent integration options as a WebLogic Workshop control increases both flexibility and ease of use. The provided Stellent control should lessen the investment required to adopt the command layer integration approach. Using it, you can quickly build rich portal and web applications that integrate with Stellent WCM.

Note that the Stellent control has been tested with Stellent Content Server version 7.5 and Stellent Content Integration Suite (CIS) Version 7.2.

References


Munish Gandhi is a Senior Consultant with the Professional Services division of BEA Systems. He has over eight years experience in software consulting and technical presales.