Lifecycle Callbacks has been edited by Andrus Adamchik (Dec 26, 2006).

(View changes)

Content:

(in 3.0 since 9/21/2006)

TODO: annotations, default callback for all entities, Modeler support

Users can register callback methods that will be invoked during the lifecycle of persistent objects. Callback mechanism matches closely the one defined in the JPA Specification (except that it works with JDK 1.4 and allows preconfigured listeners). There are seven lifecycle callbacks described below (PrePersist, PostPersist, PreUpdate, PostUpdate, PreRemove, PostRemove, PostLoad). There are two types of invocations for each one of them: callback on a persistent object itself or a callback on an arbitrary listener object.

Callbacks feature supercedes the following 1.2/2.0 features:
  • Interception of object state transitions inside "Persistent.setPersistenceState()".
  • Event mechanism defined in "org.apache.cayenne.access.event" package. Scheduled for removal in 3.0.
  • "DataObject.validateForX" - it is a good idea to use it strictly for validation; updating the state before commit should be done via callbacks.
  • "DataObject.fetchFinished()" - scheduled for removal in 3.0

Callback Method Semantics

  • No formal interface is required to mark a method to be used for callback.
  • A callback method signature looks like "void someMethod()" for persistent classes.
  • It looks like "void method(Type entityObject)" for listener classes.
  • A callback method can have an arbitrary name.
  • A callback method can use public, private, protected or default access.
  • They must NOT be static.
  • Callback methods are polymorphic - registering a callback on a superclass (even if the superclass does not map to an entity) will ensure the callback will be invoked on all entity subclasses, using the overriding subclass method if applicable.

Callback on persistent object example:

public class Artist { 
   ...

   // a vaid callback method
   protected void setDefaultProperties() {
      ...
   }
}

Callback on a listener class example:

public class MyListener { 
   ...

   // a valid callback method
   public void initArtist(Artist a) {
      ...
   }
}

Types of Callbacks

Callback Invoked...
PrePersist Within "ObjectContext.newObject()" after ObjectId and ObjectContext are set.
PreRemove Before an object is deleted inside "ObjectContext.deleteObject()"; also includes all objects that will be deleted as a result of CASCADE delete rule.
PreUpdate Prior to commit (and prior to "validateFor*") within "ObjectContext.commitChanges()" and "ObjectContext.commitChangesToParent()"
PostPersist Within "ObjectContext.commitChanges()", after commit of a new object is done.
PostRemove Within "ObjectContext.commitChanges()", after commit of a deleted object is done.
PostUpdate Within "ObjectContext.commitChanges()", after commit of a modified object is done.
PostLoad
  • Within "ObjectContext.performQuery()" after the object is fetched.
  • Within "ObjectContext.rollbackChanges()" after the object is reverted.
  • Anytime a faulted object is resolved (i.e. if a relationship is fetched.

Enabling Callbacks

TODO: expect this to be changed to something more user-friendly.

Registering listener:

DataDomain domain = ...
int callbackType = LifecycleEventCallback.PRE_PERSIST; // choose callback type you care about
domain.getEntityResolver().getCallbacks(callbackType).addListener(
				MyEntity.class, new MyListener(), "callbackMethod");

Building ObjectContext with enabled callbacks:

DataChannelCallbackInterceptor postInterceptor = new DataChannelCallbackInterceptor();
postInterceptor.setChannel(domain);
ObjectStore objectStore = new ObjectStore(domain.getSharedSnapshotCache());

ObjectContextCallbackInterceptor preInterceptor = new ObjectContextCallbackInterceptor();
preInterceptor.setContext(new DataContext(postInterceptor, objectStore));

ObjectContext userContext = preInterceptor;

Reply via email to