Change Preprocessors
Change preprocessors are server-side, user-implemented action handlers that change new or updated source objects before they are persisted to the Content Engine database. You associate a change preprocessor handler with a class definition. When a client saves an object of that class, the associated handler is triggered.
Change preprocessors allow source object modifications that are difficult or impossible to achieve with asynchronous or synchronous event action handlers. For example, a change preprocessor must be used to alter settable-only-on-create (SOOC) properties because SOOC properties cannot be changed after they are persisted. For feature comparisons between change preprocessors and event action handlers, see Action Handlers: Restrictions and Best Practices.
Change preprocessors have these characteristics:
- The source object in a create, update, or delete server request is passed to a change preprocessor handler. The source object includes a properties collection and the set of pending actions.
- You can implement a change preprocessor handler as a Java or JavaScript component. A change preprocessor that is implemented with Java can be placed in a code module, and can coexist in the same code module with other action handler types: event action, lifecycle action, and document classifier. For more information, see Deploying Java Action Handlers.
- You can set one or more change preprocessors on a subscribable
class definition, such as
Document. For more information, see Setup Requirements. - A change preprocessor set on a class is applied recursively to
subclasses in the class hierarchy. For example, if you set a change
preprocessor on the Document class, it is also applied logically to
the subclasses of the Document class. All enabled preprocessors that
are associated with the source object's class hierarchy are loaded
and called per change request, regardless of whether the change is
for create, update, or delete.
If the same preprocessor is referenced multiple times within a hierarchy, the preprocessor nearest the root of the hierarchy is started and all others are silently skipped. For more information, see Change preprocessor definitions.
- A change preprocessor runs synchronously, so an exception rolls back the entire transaction.
- If auditing is enabled, the audit log entry shows the changes that are made by change preprocessors. Change preprocessors are started before audit processing.
- Unless disabled, change preprocessors are started unconditionally.
- Changes that are made within a preprocessor can be persisted only if the request's starting user has the required permissions and if property constraints are not violated.
Implementation Guidelines
You implement the following method in the ChangePreprocessor interface:
boolean
preprocessObjectChange(com.filenet.api.core.IndependentlyPersistableObject
sourceObj) In implementing this method, consider the following points:
- You can retrieve the source object's pending actions array to perform conditional processing. A PendingAction object represents an intended change to the source object submitted by the client, which has not yet been performed by the server, such as a move content, update, or check-out action. By iterating the pending action array, you can control when the change preprocessor updates source object properties based on the actions that are submitted by the client. For a code example, see Creating a Change Preprocessor Handler.
- You can retrieve the source object's property collection. The
properties collection reflects the current state of the source object,
along with any yet-to-be-persisted changes from the client.
For creation requests to the server, the property collection is sparse; it contains only client-provided property values, any default values associated with properties not set by the client, and a few other properties that are determined by the object type.
On update and delete requests to the server, the collection contains all properties that are currently defined on the object that is merged with those properties that are modified by the client.
Because a change preprocessor handler runs regardless of the type of request to the server (create, update, delete), you cannot rely on all the properties being available in the source object's properties collection. Therefore, before you attempt to retrieve a property, it is recommended that a change preprocessor implementation call the
IsPropertyPresentmethod to verify that the property is in the collection. - A side effect of a check-out on a current version is that a reservation object gets passed as a source object. In this case, the properties collection that is passed to the preprocessor includes any reservation properties that are submitted with the action, plus any copy-to-reservation properties from the originating source object. Therefore, a property definition with a CopytoReservation property set to false prevents a property instance from being copied to a reservation object's collection. For example, the MimeType property cannot be copied to the collection because of property definition constraints.
- If a preprocessor changes the properties collection, return
trueto persist the collection to the server. Otherwise, iffalseis returned, the changes to the properties collection are lost (not persisted). - If a chain of preprocessors runs recursively in the class hierarchy,
the preprocessors in the chain can see the property updates applied
from the previously started preprocessors that returned
true. The properties collection is not persisted until after all preprocessors are started.
Allowed Operations
- You can implement updates to the source object's properties collection.
An implementation can use
fetchPropertyto perform conditional processing based on property values of object-valued properties (OVPs). - You can remove properties from a collection. Note that you must remove fabricated properties; that is, properties that are not defined in a class definition, but have meaning only between a client and a preprocessor. If you do not remove fabricated properties, the Content Engine throws an exception.
- Because change preprocessors are started before pending action processing, you can retrieve the source object's pending actions array.
Disallowed Operations
You cannot start the following operations, which adversely affect the source object's persistence:
- Methods of IndependentlyPersistableObject that modify the
object, like
fetchProperties(),checkout(),save(),refresh(),addPendingAction(),clearPendingActions(),delete(), andsetUpdateSequenceNumber(). - Content access methods, like
setCaptureSource()andaccessContentStream().
Setup Requirements
To set up a change preprocessor:
- Implement the
ChangePreprocessorinterface. - Create a CmChangePreprocessorAction object. This object contains a property for setting the implemented ChangePreprocessor interface. It also includes an IsEnabled property, allowing an administrator to disable a preprocessor at the system scope, no matter where it is referenced in the class hierarchies.
- Create a CmChangePreprocessorDefinition object. This object contains a property for setting the implemented ChangePreprocessorAction object. It also includes an IsEnabled property, allowing an administrator to disable a preprocessor at the class scope.
- Create a CmChangePreprocessorDefinitionList object and
add the
CmChangePreprocessorDefinitionobject to it. - Get the SubscribableClassDefinition object that represents the class definition on which you want to set the change preprocessor.
- Set
CmChangePreprocessorDefinitionListon theSubscribableClassDefinitionobject and save it.
You can get all CmChangePreprocessorAction objects
with the ObjectStore.CmChangePreprocessorActions property.
You can get all CmChangePreprocessorDefinition objects
with the SubscribableClassDefinition.ChangePreprocessorDefinitions property.
For code examples of setup and retrieval operations, see Working with Change Preprocessors.