Writing Server Workflow Methods
Writing Server Workflow Methods
Changes to the workflow engine in the Content Server version 5.1 provide better functionality, performance and stability when writing workflow methods. This paper outlines best practices and tips for developing and deploying Java methods.
- General Best Practices and Tips.
- Download a Sample Method.
- Implementing the Method.
- Bug Submissions.
General Best Practices and Tips
- Always implement the IDmMethod interface in your class,
- Implement the method execute(),
- Obtain a Docbase session using newSessionManager()
- Retrieve packages from the work item
- Throw an exception instead of using 'exit',
- Release your session after use.
Always implement the IDmMethod interface in your class.
Documentum provides the Apache Tomcat Java method server as a component of the Content Server installation. In addition to Tomcat, Documentum provides a servlet called DO_METHOD to execute methods. The compiled servlet code is found in mthdservlet.jar located on the same host as Content Server, this jar file contains the IDmMethod class. The programs launched with DO_METHODs sent to the Java method server implement IDmMethod and be stored in %DOCUMENTUM%\dba\java_methods directory. When a DO_METHOD method directed to the Java method server is issued, it generates an internal HTTP_POST request. The Java method server invokes the do_method servlet to service the request.
The code extract below shows the class declaration including implementing the IDmMethod interface.
import com.documentum.mthdservlet.IDmMethod; import java.util.*; import ... public class DmWorkflowPromoteLifecycle implements IDmMethod { ... |
Implement the method execute().
The Java Method Server expects a method called 'execute' to exist and will invoke it. Use this method as you would use main() in a normal Java class. The execute() method takes two parameters:
- The arguments passed to the method from the workflow engine, these are passed in as key-value pairs in a java.util.Map datastructure.
- A pointer to a Java 'OutputStream'; anything written to this OutputStream will be written to the log file as defined in the log4j configuration
The code extract below is an example of the execute method declaration.
public class DmWorkflowPromoteLifecycle implements IDmMethod { protected IDfSessionManager m_sessionMgr = null; protected String ... private static final String USER_KEY = "user"; private static final ... private Object val; private String ... public void execute(Map params, OutputStream ostream) throws Exception { ... |
Obtain a Docbase session using newSessionManager().
Using the values passed by the server to the workflow method for user name, login ticket (or password), and Docbase name, call the DfClient.newSessionManager() method to construct a new IDfSessionManager object. The IDfSessionManager object encapsulates one or more “managed” DFC session objects and dynamically manages the session pool.
protected IDfSessionManager login() throws DfException { if (m_docbase == null || m_userName == null || m_ticket == null ) return null; // now login IDfClient dfClient = DfClient.getLocalClient(); if (dfClient != null) { IDfLoginInfo li = new DfLoginInfo(); li.setUser(m_userName); li.setPassword(m_ticket); li.setDomain(null); IDfSessionManager sessionMgr = dfClient.newSessionManager(); sessionMgr.setIdentity(m_docbase, li); return sessionMgr; } return null; } } |
Retrieving Packages from Work Item.
It is common for the workflow method to need to interact with the work items in its package. In the example below the method will promote the work items. In order to do this we first need to get a 'handle' on each item. The dmi_package.r_component_id contains the object IDs of all of the SysObjects in the workflow's package. The code below shows you how to iterate through all of the items in the package, get a reference to the objects and promote them.
Note that you must 'acquire' the workflow item before starting and 'complete' it once you have finished.
IDfId workitemID = new DfId(m_workitemId); session = sessionManager.getSession(m_docbase); IDfWorkitem workitem = (IDfWorkitem)session.getObject(workitemID); workitem.acquire(); lifeCycleState = null ; lifeCycleOverride=false ; lifeCycleTestOnly =false ; IDfCollection pkgColl = null; pkgColl = workitem.getPackages(""); if (pkgColl != null) { while (pkgColl.next()) { String docId = pkgColl.getString("r_component_id"); ostream.write(docId.getBytes()); int docCount = pkgColl.getValueCount("r_component_id"); for (int i=0; i <=(docCount-1); i++) { docIdObj = pkgColl.getRepeatingId("r_component_id", i); if (docIdObj!=null) { IDfId sysobjID = new DfId(docId); IDfSysObject doc = (IDfSysObject)session.getObject(sysobjID); doc.promote(lifeCycleState, lifeCycleOverride, lifeCycleTestOnly); } } } pkgColl.close(); } workitem.complete(); |
Throw an exception instead of using 'exit()'.
When using Docbasic, if you wanted to exit from a workflow method and pass back a failure code you used the exit() method. From a Java server method you can, and should, throw an exception instead.
You can make use of the standard Java exception handling to catch any exceptions in your code, perform any functions and then throw the error back to the workflow engine. In the example below we write the exception details to the OutputStream, dump the stack trace to stderr and then throw the error.
public void execute(Map params, OutputStream ostream) throws Exception { Do something ... } catch (DfException e) { ostream.write("A DfException occurred".getBytes()); ostream.write(e.getMessage().getBytes()); e.printStackTrace(); // spit out to stderr as well throw e; } finally { if ( session != null ) sessionManager.release(session); } |
Release your session after use.
Don’t forget to release your session once you have finished with it. You can ensure that this happens by wrapping the release code in a 'finally' block.
public void execute(Map params, OutputStream ostream) throws Exception { Do something ... } catch (DfException e) { ostream.write("A DfException occurred".getBytes()); ostream.write(e.getMessage().getBytes()); e.printStackTrace(); // spit out to stderr as well throw e; } finally { if ( session != null ) sessionManager.release(session); } |
Download a Sample Method.
We have included a sample server method for you to try, it is the method used in the examples in this article. This method will promote the objects in the package. Download the method.
Implementing the Method.
Once you have written your workflow method you will have to implement it. The following are the steps required to implement a Java workflow method.
- Compile the Java method. Note that if you make changes to the workflow method, you must re-compile the method and restart the Java Method Server for the changes to take effect.
- Copy the .class file to the %DOCUMENTUM%\dba\java_methods directory on the server machine.
- Create the method object to reference this method. Specify:
- Type: java
- Command verb: java
For methods implementing IDmMethod and executed by the Java Method Server, it is a good practice to specify the fully-qualified class name of the Java class as the command verb. If your class is contained with a jar file then you must specify the fully-qualified class name. For example;
com.documentum.bpm.bpsintegration.bps.DmBPSHTTPIntegration