Custom lifecycle modules are a very powerful tool for Documentum developers in that they allow the addition of custom business logic to lifecycle states. This article shows you how to create custom Java lifecycle modules for Documentum.
Blue Fish Development Group
701 Brazos St. #700
Austin, TX 78701
(512) 469-9300
Custom lifecycle modules are a very powerful tool for Documentum developers in that they allow the addition of custom business logic to lifecycle states. This article shows you how to create custom Java lifecycle modules for Documentum.
Documentum lifecycles are used to implement business policies around the lifecycle of an object in the repository. For example, a news article might be authored in “Draft” state, then promoted to a “QC Review” state, and if accepted by an editor, promoted to “Final” or “Published” state. Each state in the lifecycle can be configured to perform certain actions as documents enter or leave it.
Some lifecycle actions, such as adding or removing version labels or assigning a new ACL, can be achieved through configuration of the out-of-the-box lifecycle functionality. However, more specialized actions require custom-coded lifecycle modules, which are the subject of this article.
This article assumes that the reader knows the basics of lifecycle creation and configuration. If you are unfamiliar with these concepts, please see the Documentum Content Server Fundamentals Guide (Chapter 10) or this excellent article from the dm_developer website:
Creating a Simple LifecycleDocument lifecycles (dm_policy objects) are typically constructed and administered via the Documentum Application Builder (DAB) interface. This article focuses on lifecycle configuration performed in the DAB client. You could also perform most of these tasks using DQL, the API, or DFC. Custom Java code for lifecycles can be written in the editor/IDE of your choice.
Documentum lifecycles have an implementation type attribute which defaults to “Docbasic”. This value sets the code language for modules that can be called from the lifecycle’s state transitions. (A state transition is the promotion or demotion of an object to a different lifecycle state.) Because a lifecycle can only have one implementation type, it can only execute one type of code. When using custom code modules written in Java, set the lifecycle’s implementation attribute to “Java” as described below.

Figure 1: Setting the Lifecycle’s Implementation Type
Lifecycles can call custom code modules during state transitions. Each lifecycle state transition provides three opportunities to call custom code:
When you create a code module for your custom lifecycle code in DAB, it is automatically assigned the “BOF_acl” ACL which has permissions of Owner(Delete) and World(Read + Execute Procedure). These permissions allow the lifecycle to execute modules on behalf of any user (World) who initiates a state transition. However, if the custom code itself tries to perform activities for which the lifecycle user does not have sufficient permssion then the following error is raised in the WDK client:

Figure 2: Error raised by lifecycle code executing with insufficient permission
If your custom lifecycle code needs to perform actions for which the individual lifecycle user does not have permission, then you can configure lifecycle actions to operate on behalf of a designated superuser (or any other user), rather than the lifecycle user. This configuration is stored in the “a_bpaction_run_as” attribute of the docbase configuration object, “dm_docbase_config”. These are the valid values for the Docbase-level a_bpaction_run_as attribute:
You can configure lifecycle actions to run on behalf of the desired user by executing a DQL command similar the one shown below:
Important Note: Configuring lifecycle actions to operate on behalf of another user can have the unintended side-effect of setting the document’s ‘Modified By’ attribute (r_modifier) to the name of the designated user (a_bpaction_run_as), rather than the user who initiated the lifecycle state transition.
In order for custom code to be callable from lifecycle states, it must implement the correct interface(s). A single Java class can implement multiple interfaces and thus handle multiple events in the state transition. A single lifecycle state transition has three events that can call out to your custom code: pre-entry, action, and post-entry. The method signatures for each event are different, but their parameters are all the same:
The method signatures for the lifecycle state-transition events are described below.
A pre-entry lifecycle module must implement the IDfLifecycleUserEntryCriteria interface. This interface has a single public method, userEntryCriteria, which returns a Boolean value. A return value of True allows the object to enter the lifecycle state. A return value of False or an exception will prevent the object from entering the target lifecycle state.
Interface:IDfLifecycleUserEntryCriteria
Method Signature:
public boolean userEntryCriteria ( IDfSysObject obj,
String userName,
String targetState) throws DfException {
return true;
}
A lifecycle action module must implement the IDfLifecycleUserAction interface. This interface has a single public void method, userAction, in which you can perform custom actions on the object that is entering the lifecycle state. Errors raised in custom lifecycle action code will not prevent an object from entering the lifecycle state.
Interface:IDfLifecycleUserAction
Method Signature:
public boolean userAction ( IDfSysObject obj,
String userName,
String targetState) throws DfException {
}
A post-entry lifecycle module must implement the IDfLifecycleUserPostProcessing interface. This interface has a single public void method, userPostProcessing, in which you can perform custom actions on the object after it has entered the lifecycle state. Errors raised in custom lifecycle post-entry code will not prevent an object from entering the lifecycle state.
Interface:IDfLifecycleUserPostProcessing
Method Signature:
public boolean userPostProcessing ( IDfSysObject obj,
String userName,
String targetState) throws DfException {
}
Code in lifecycle modules can retrieve a user session from the SysObject parameter.
If the docbase is configured to run lifecycle methods as a special user/superuser, then a session will be returned for that specific user. Otherwise, the command will return a session for the user who initiated the lifecycle state transition (this is the default behavior).
After you have created a Java class that implements one or more of the lifecycle state transition interfaces, add it to its own jar file and copy the jar file to a location where it can be accessed via DAB. Note that lifecycle modules do NOT require you to package separate interface and implementation classes in your jar file (as is the case for TBO and SBO modules). Only the implementation class is necessary for lifecycle modules.
Before your custom code can be called from a lifecycle it must first be added to the Docapp (and docbase) as a custom code module. This can be done via the Insert->Module feature of Documentum Application Builder (DAB) client.

Figure 3: Creating a new code module in DAB
Important Note: You will have to manually type the word “Lifecycle” into the module type drop-down box because it will not appear as an option.
When you check-in the new module in the Docapp, a new folder of type dmc_module is created in the Lifecycle Modules area of the docbase containing the module’s jar file(s) as dmc_jar objects.

Figure 4: A custom lifecycle module stored in the docbase
Now that the custom code has been packaged and added to the docapp as a lifecycle module, the lifecycle states can be configured to call the module.

Figure 5: Configuring the lifecycle state to call a custom pre-entry module in DAB
Note: If your module does not include a class that implements the corresponding interface, for the transition event then your module will not appear as a choice for the state transition in DAB.
All of the lifecycle state transition interfaces throw DfException. If custom code within your module throws other types of errors, it’s a good idea to roll them up to a DfException and set the error message string to something meaningful. The custom error message will be displayed to the transition initiator in WDK clients. The code snippet below shows how to create a DfException, set its error message string, and throw it.
DfException ex = new DfException();
ex.setMessage("Hello this is a problem");
throw ex;
Best Practice: In pre-entry methods, when an object fails validation, it’s a good idea to raise a DfException and set the error message string to something specific and informative, rather than to simply return False. If you only return a value of False, then a generic error message is returned to the user in the WDK client that gives no indication as to what specifically caused the validation issue.

Figure 6: A pre-entry validation error showing a custom error message
Custom lifecycle modules are a very powerful tool for Documentum developers in that they allow the addition of custom business logic to lifecycle states. Documentum’s out-of-the-box lifecycle functionality is extensive and often covers a solution’s business requirements solely through configuration. However, business requirements sometimes fall outside of the capabilities of the standard Documentum lifecycle feature set. This is where custom lifecycle modules can really save the day!
If you have any questions or comments about this article, please feel free to contact the author at gtarrant@bluefishgroup.com.
Subscribe to our newsletter to be notified when new articles are posted. You can unsubscribe at any time.
This solution is very very good. i will give this 5(*****)
Sushil Shirsath | July 24th, 2008 3:12 am