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 IsPropertyPresent method
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 true to
persist the collection to the server. Otherwise, if false is
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 fetchProperty to 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(),
and setUpdateSequenceNumber().
- Content access methods, like setCaptureSource() and accessContentStream().
Setup Requirements
To set up a change
preprocessor:
- Implement the
ChangePreprocessor interface.
- 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 CmChangePreprocessorDefinition object
to it.
- Get the SubscribableClassDefinition object that represents
the class definition on which you want to set the change preprocessor.
- Set CmChangePreprocessorDefinitionList on the SubscribableClassDefinition object
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.