IBM FileNet P8, Version 5.2            

Deploying Java Action Handlers

You can store an action handler as a CodeModule object in a Content Engine object store, or, alternatively, you can specify the action handler in the Java™ Virtual Machine (JVM) classpath of the application server where the Content Engine is running. For testing an action handler, it is easier to update it when it is referenced in the JVM classpath. For deploying an action handler in an enterprise production environment, it is more efficient to store an action handler and any supporting libraries as a CodeModule object on the Content Engine. Code modules are automatically available when deploying the Content Engine to multiple application server instances, or moving your content metadata from one system to another. If you reference action handlers in the JVM classpath, you must manually distribute them to new systems.

Other code module characteristics are as follows:

This topic shows you how to reference action handlers and supporting libraries in the WebLogic and WebSphere® classpaths. It also shows how to use the Content Java and .NET APIs to create and update a code module that is stored in the Content Engine. It is important to keep in mind that if you later modify an action handler, then you must update the CodeModule object and the Action object that references the code module.

Referencing Action Handlers in the Classpath

For testing action handlers, it is generally easier to reference them in the classpath of your application server rather than store them as CodeModule objects in the Content Engine. There are various ways of setting the classpath, some of which are described below. For additional information on setting classpaths, see the documentation for your application server.

For WebLogic, reference an action handler or supporting library in the CLASSPATH variable in the Content Engine launch script, startWebLogic.sh or startWebLogic.cmd. The Content Engine launch script is in the WebLogic domain where you installed the Content Engine, such as FNCEDomain.

For WebSphere, you can reference an action handler or supporting library in the CLASSPATH in any of the following ways:

Restart the application server after updating the classpath.

Note: The Windows environment has a command line size limit, which can be exceeded by a CLASSPATH variable set to a very long string. For Windows 2000 and NT 4.0, the limit is 2,047 characters. For Windows XP and newer operating systems, the limit is 8,191 characters.

Creating a CodeModule Object

The easiest way to create a code module is with Administration Console for Content Platform Engine. However, as described in this section, you can also programmatically create a CodeModule object.

In the Java and C# examples below, EventHandlers.jar containing multiple action handlers is checked into the CodeModules folder of the object store. Given that the content of a CodeModule object can consist of class or JAR files, the code tests for the type of Java module in order to set the ContentType property on the ContentTransfer object. Note that you must check in a CodeModule object. If you do not, it is stored as a reservation (in progress) version of a CodeModule object, which will result in an exception when you attempt to create the Action subobject.

Also included in the examples is optional code that demonstrates a point about creating an Action subobject in the same procedure that creates the CodeModule object. Such a procedure would be useful in an event action creation wizard that gives users the option to create the code module. If you code a procedure that creates both objects, you should trap for a potential exception in creating the Action subobject, and delete the previously created CodeModule object in the catch block. If you do not, and if an exception occurs, then a copy of the first CodeModule object will be created when the code is rerun. Potential errors that will throw a creation exception are failing to check in a CodeModule object, or setting the Action subobject's ProgId property to the wrong value.

Java Example

...
// Create a File object for the JAR containing the event handlers.
File handlerJar = new File("C:\\EclipseWorkspace\\EventHandlers\\EventHandlers.jar");
// non-Windows: File handlerJar = new File("/EclipseWorkspace/EventHandlers/EventHandlers.jar");

// Get object for existing folder where JAR will be stored in object store.
Folder folder=Factory.Folder.fetchInstance(os, "/CodeModules", null);

// Create ContentTransfer object from JAR content.
ContentElementList contentList = Factory.ContentTransfer.createList();
ContentTransfer ctNew;
FileInputStream fileIS;
ctNew = Factory.ContentTransfer.createInstance();
fileIS = new FileInputStream(handlerJar.getAbsolutePath());
ctNew.setCaptureSource(fileIS);

// Set mime type based on whether the Java module is a class or JAR.
String fileName = handlerJar.getName();
if (fileName.endsWith(".class"))
{
   ctNew.set_ContentType("application/java-byte-code");
}
else if (fileName.endsWith(".jar"))
{
   ctNew.set_ContentType("application/java-archive");
}

// Add content element to list, which will be added to CodeModule object (below).
contentList.add(ctNew);

// Create CodeModule object.
CodeModule newCM = Factory.CodeModule.createInstance(os, "CodeModule"); 
// Set DocumentTitle property.
String propertyName = "DocumentTitle";
newCM.getProperties().putValue(propertyName, "Java Event Handlers");
// Add content element to CodeModule object.
newCM.set_ContentElements(contentList);

// Check in CodeModule object.
newCM.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
newCM.save(RefreshMode.REFRESH);

// File CodeModule object and save.
DynamicReferentialContainmentRelationship drcr 
   = (DynamicReferentialContainmentRelationship)folder.file((IndependentlyPersistableObject)newCM,
      AutoUniqueName.AUTO_UNIQUE,
      "Java Event Handlers",
      DefineSecurityParentage.DO_NOT_DEFINE_SECURITY_PARENTAGE);
drcr.save(RefreshMode.NO_REFRESH);
//////////////////////////////////////////////
// The following code is optional. It demonstrates creating an Action subobject,
// in this case, EventAction, with exception handling code.
try
{
   EventAction eventAction = Factory.EventAction.createInstance(os, null);
   eventAction.set_ProgId("RenameActionHandler");
   eventAction.set_CodeModule(newCM);
   eventAction.set_DisplayName("EventActionWithCodeModule");
   eventAction.save(RefreshMode.REFRESH);
}
catch (Exception e)
{
   System.out.println("EventAction creation failed: " + e.getMessage());
   newCM.delete();
   newCM.save(RefreshMode.REFRESH);
}

C# Example

...
// Create a FileInfo object for the JAR containing the event handlers.
FileInfo handlerJar = new FileInfo (@"C:\\EclipseWorkspace\\EventHandlers\\EventHandlers.jar");

// Get object for existing folder where JAR will be stored in object store.
IFolder folder = Factory.Folder.FetchInstance(os, "/CodeModules", null);

// Create ContentTransfer object from JAR content.
IContentElementList contentList = Factory.ContentTransfer.CreateList();
IContentTransfer ctNew;
FileStream fileS = handlerJar.OpenRead();
ctNew = Factory.ContentTransfer.CreateInstance();
ctNew.SetCaptureSource(fileS);

//Set mime type based on whether the Java module is a class or JAR.
string filename = handlerJar.Name;
if (filename.EndsWith(".class"))
{
   ctNew.ContentType = "application/java-byte-code";
}
else if (filename.EndsWith(".jar"))
{
   ctNew.ContentType = "application/java-archive";
}

// Add content element to list, which will be added to CodeModule object (below).
contentList.Add(ctNew);

// Create CodeModule object.
ICodeModule newCM = Factory.CodeModule.CreateInstance(os, "CodeModule");

// Set DocumentTitle property.
newCM.Properties["DocumentTitle"] = "Java Event Handlers");

// Add content element to CodeModule object.
newCM.ContentElements = contentList;

// Check in CodeModule object.
newCM.Checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
newCM.Save(RefreshMode.REFRESH);

// File CodeModule object and save.
IDynamicReferentialContainmentRelationship drcr
   = (IDynamicReferentialContainmentRelationship) folder.File((IIndependentlyPersistableObject)newCM,
      AutoUniqueName.AUTO_UNIQUE,
      "Java Event Handlers",
      DefineSecurityParentage.DO_NOT_DEFINE_SECURITY_PARENTAGE);
drcr.Save(RefreshMode.NO_REFRESH);
//////////////////////////////////////////////
// The following code is optional. It demonstrates creating an IAction subobject,
// in this case, IEventAction, with exception handling code.
try
{
   IEventAction eventAction = Factory.EventAction.CreateInstance(os, null);
   eventAction.ProgId = "RenameActionHandler";
   eventAction.CodeModule = newCM;
   eventAction.DisplayName = "EventActionWithCodeModule";
   eventAction.Save(RefreshMode.REFRESH);
}
catch (Exception e)
{
   System.Console.WriteLine("EventAction creation failed: " + e.Message );
   newCM.Delete();
   newCM.Save(RefreshMode.REFRESH);
}

Updating a CodeModule Object

If you modify an action handler that is contained within a CodeModule object, you must first update the CodeModule object with the new version of the action handler. Then you must update any Action subobjects that reference the code module that has been updated. The easiest way to update a CodeModule object and Action subobjects is with an Administration Console for Content Platform Engine, as described in Managing event actions. However, you can update these objects programmatically, as described in this section.

The Java and C# examples below illustrate the update process for an event handler that has been previously archived in EventHandlers.jar, which is contained in a CodeModule object. Once the handler has been modified and re-archived in EventHandlers.jar, the CodeModule object is ready to be updated with the new version of EventHandlers.jar.

First, the content of the new JAR is retrieved as a ContentTransfer object and stored in a ContentElementList. Next, the current version of the CodeModule object is checked out, a reservation object is retrieved, and the ContentElementList is set on the reservation object. The reservation object is checked in, becoming the new version of the CodeModule object.

The CodeModule object that has been updated is referenced by an EventAction object, and it must be updated to reference the current version of the CodeModule object. As shown in the second part of the examples, the EventAction object's CodeModule property is set to the current version of the CodeModule object.

Java Example

...
// Create a File object for the JAR containing the updated event handler.
File newHandlerVersion = new File("C:\\EclipseWorkspace\\EventHandlers\\EventHandlers.jar");
// non-Windows: File newHandlerVersion = new File("/EclipseWorkspace/EventHandlers/EventHandlers.jar");
           
// Create ContentTransfer object from updated JAR content.
ContentElementList contentList = Factory.ContentTransfer.createList();
ContentTransfer ctNew;
FileInputStream fileIS;
ctNew = Factory.ContentTransfer.createInstance();
fileIS = new FileInputStream(newHandlerVersion.getAbsolutePath());
ctNew.setCaptureSource(fileIS);
ctNew.set_ContentType("application/java-archive");
contentList.add(ctNew);

// Check out current version of CodeModule object.
CodeModule cm = Factory.CodeModule.getInstance(os, "/CodeModules/EventHandlers.jar");
cm.checkout(com.filenet.api.constants.ReservationType.EXCLUSIVE, null, null, null);
cm.save(RefreshMode.REFRESH);

// Get reservation object from the checked-out code module.
// This will become the new version of the code module.
CodeModule cmUpdate = (CodeModule) cm.get_Reservation();


// Set the new content on the reservation object.
cmUpdate.set_ContentElements(contentList);

// Check in the new version of the code module.
cmUpdate.checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
cmUpdate.save(RefreshMode.REFRESH);
 
/////////////////////////////////////////////
// Get event action to update its CodeModule property.
PropertyFilter pf = new PropertyFilter();
pf.addIncludeType(1, null, null, FilteredPropertyType.SINGLETON_OBJECT, new Integer(1) );
pf.addIncludeProperty(0, null, Boolean.TRUE, PropertyNames.CODE_MODULE, new Integer(1) );
EventAction eventAction = Factory.EventAction.fetchInstance(os, new Id("{94AF1BB3-A4A7-4851-9067-D6F88005C470}"), pf); 

// Set CodeModule property.
eventAction.set_CodeModule(cmUpdate);

eventAction.save(RefreshMode.REFRESH); 
}

C# Example

...
// Create a Stream object for the JAR containing the updated event handler.
Stream fileStream = File.OpenRead(@"C:\\EclipseWorkspace\\EventHandlers\\EventHandlers.jar");

// Create IContentTransfer object from updated JAR content.
IContentElementList contentList = Factory.ContentTransfer.CreateList();
IContentTransfer ctNew;
ctNew = Factory.ContentTransfer.CreateInstance();
ctNew.SetCaptureSource(fileStream);
ctNew.ContentType = "application/java-archive";
contentList.Add(ctNew);

// Check out current version of CodeModule object.
ICodeModule cm = Factory.CodeModule.GetInstance(os, "/CodeModules/EventHandlers.jar");
cm.Checkout(ReservationType.EXCLUSIVE, null, null, null);
cm.Save(RefreshMode.REFRESH);

// Get reservation object from the checked-out code module.
// This will become the new version of the code module.
ICodeModule cmUpdate = (ICodeModule)cm.Reservation;

// Set the new content on the reservation object.
cmUpdate.ContentElements = contentList;

// Check in the new version of the code module.
cmUpdate.Checkin(AutoClassify.DO_NOT_AUTO_CLASSIFY, CheckinType.MAJOR_VERSION);
cmUpdate.Save(RefreshMode.REFRESH);

/////////////////////////////////////////////
// Get event action to update its CodeModule property.
PropertyFilter pf = new PropertyFilter();
pf.AddIncludeType(1, null, null, FilteredPropertyType.SINGLETON_OBJECT, 1);
pf.AddIncludeProperty(0, null, true, PropertyNames.CODE_MODULE, 1);
IEventAction eventAction = Factory.EventAction.FetchInstance(os, new Id("{94AF1BB3-A4A7-4851-9067-D6F88005C470}"), pf);

// Set CodeModule property.
eventAction.CodeModule = cmUpdate;

eventAction.Save(RefreshMode.REFRESH);
}


Feedback

Last updated: October 2013
server_procedures.htm

© Copyright IBM Corporation 2014.
This information center is powered by Eclipse technology. (http://www.eclipse.org)