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 Java-implemented change preprocessor 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. See Deploying Java Action Handlers.
- You can set one or more change preprocessors on a subscribable
class definition, such as Document. 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
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.
Should the same preprocessor
be multiply referenced within a hierarchy, the preprocessor nearest
the root of the hierarchy is invoked and all others are
silently skipped. For more about change preprocessor behavior
in a class hierarchy, 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
made by change preprocessors. Change preprocessors are invoked
prior to audit processing.
- Unless disabled, change preprocessors are invoked unconditionally.
- Changes made within a preprocessor can only be persisted if the
request's invoking user has the permissions required to make
the changes, 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:
- 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, but that 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 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, containing only client-provided property values,
any default values associated with properties not set by
the client, along with a few other properties depending on object
type.
On update and delete requests to the
server, the collection will contain all properties currently
defined on the object merged with those 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 properties being available in the
source object's properties collection. Therefore, before attempting
to retrieve a property, a change preprocessor implementation
should use the IsPropertyPresent method
to check that the property is in the collection before attempting
to get it.
- A side effect of a checkout on a current version is that a reservation
object gets passed as a source object. In this case, the properties
collection passed to the preprocessor includes any reservation
properties 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 makes changes to the properties collection,
return true to persist the collection to
the server. If it makes changes and returns false,
the changes to the properties collection are lost (not persisted).
- If a chain of preprocessors run recursively in the class hierarchy,
the preprocessors in the chain can see the property updates
applied from the previously invoked preprocessors that returned true.
The properties collection is not persisted until after all
preprocessors have been invoked.
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 residing
on 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 only have meaning between
a client and a preprocessor. If you do not remove fabricated properties,
the Content Engine throws
an exception.
- Because change preprocessors are invoked prior to pending action
processing, you can retrieve the source object's pending actions
array.
>Disallowed Operations
You cannot invoke operations that adversely impact the source
object's persistence. Such operations include the following:
- 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 these setup and retrieval operations, see Working with Change Preprocessors.