Sometimes during the execution of Escalations and Workflow processes in Maximo it is necessary for customers to implement additional processing or logic that may be specific to their business needs and/or processes. Maximo provides a simple yet powerful hook into the Maximo Business Object (MBO) framework in the form of an action custom class. Customers can develop and write their own customization's using the Java programming language and register them inside the Action application. The custom actions can then be invoked from an Escalation or a Workflow process.
These days the utilization of Maximo action custom classes has become rampant especially since customers and clients are looking to streamline and automate business processes and deliver immediate business value. Due to the proliferation of action custom classes at customer sites we feel it's necessary to provide details that will help the developer effectively implement and deploy custom classes and that is the intent of this post. This post does not cover details like building and deploying the EAR file. Please refer to the System Administrator Guide (SAG) for those type of details.
What is a Maximo Action Custom Class?
In a nutshell a Maximo action custom class is an implementation of a java interface provided out of the box in all Maximo/TPAE based products. Located inside the psdi.common.action package the ActionCustomClass needs to be implemented when customers want to write custom code to solve or address their specific business needs. The interface is very simple and has only one method the developer has to implement called applyCustomAction().
The snippet below shows a typical example of how to implement the ActionCustomClass.
public class CommLogSendMessage implements ActionCustomClass
* Get the commlog records for the given MBO and send it. If the send fails again the record will remain flagged as failed and can be retried again.
public void applyCustomAction(MboRemote mbo, Object params) throws MXException, RemoteException
MboSetRemote commlogset = mbo.getMboSet("COMMLOG");
if (commlogset != null)
CommLogRemote commlog = (CommLogRemote)commlogset.fetchNext() ;
while (commlog != null)
} catch (MXException e)
commlog.setValue("issendfail", true, MboConstants.NOACCESSCHECK);
commlog = (CommLogRemote)commlogset.fetchNext();
The ApplyCustomAction() method is the entry point to the ActionCustomClass object. This method has to be implemented and your custom code should be initiated from inside this method. The business object (MBO) attached to the custom action is passed into this method so you can do things like get a MboSet via a relationship and iterate thru the set like in the example above. The method also throws a MXException so typically there is no need to handle Maximo exceptions unless you want to do something specific with the exception (like writing the error to a logger) in which case you would use a try/catch block inside your code. If you do catch a MXException it's always good practice to throw the error back so Escalations and WorkFlow can handle the exception within their constructs. Not the case in the code snippet above!
Digging deeper ...
An escalation or workflow invokes an ActionCustomClass by dynamically loading and initializing the class during runtime. The life cycle of the objects derived from the ActionCustomClass is managed by the Java Virtual Machine (JVM). The JVM keeps track of all the classes that have been loaded and NOT Maximo. Once a static reference to the Class is obtained using Java Reflection
, Maximo derives or instantiates a new object and invokes the ApplyCustomAction() through Java reflection. For more details on the Java reflection API click here
It is important to note that for every MBO that is processed through an escalation or a workflow that invokes an ActionCustomClass a new ActionCustomClass object is instantiated each time. For example if an escalation is invoking an ActionCustomClass on 500 service request MBO's Maximo will derive a new ActionCustomClass object for each record or MBO. The destruction of the object is managed by the JVM and the Java garbage collector. For more information on best practices and fine tuning IBM's java garbage collector please refer to the this document.
There are two kinds of exceptions thrown by the applyCustomAction() method and handled by escalations and workflow processses, MXException and RemoteException. Details for RemoteException can be found here. All Maximo related exceptions are wrapped or nested inside a MXException so it's not necessary to handle those inside a try/catch block. If you do handle a MXException inside your ActionCustomClass it is important to throw it back so the caller (escalations or workflow) can handle it within their constructs. There are exceptions to this rule as seen in the code snippet above. Depending on what you're doing inside the ActionCustomClass it's your responsibility to handle all other exceptions adequately.
Both escalations and workflow processes call the save() method on the owner MboSet. Therefore it is not necessary to call the save() method on any MboSet that is derived from the MBO that is passed into the ApplyCustomAction() method. Calling the save() method on any MboSet that is derived from the passed in MBO will save the transaction and may cause subsequent records in the set to not be processed.
A couple of final thoughts ...
While designing an ActionCustomClass it is always a good idea to keep it simple. Define exactly what you're trying to accomplish well before writing a single line of code. Always try to work within the constructs of the MBO framework. Do not try to connect to the database directly and perform complex SQL queries. Last but not least avoid calling save() on a MboSet.
Starting with Maximo/TPAE 7.5 we now support scripting as an out of the box feature. Customers can leverage this functionality in addtion to writing custom action classes.