It is often necessary to perform various actions at different stages
of a persistent object's lifecycle. JDO includes two mechanisms for
monitoring changes in the lifecycle of your persistent objects: the
InstanceCallbacks interface, and the
InstanceLifecycleListener event framework.

Your persistent classes can implement the
InstanceCallbacks
family of interfaces to to receive callbacks when certain JDO
lifecycle events take place. There are four callbacks available:
The LoadCallback.jdoPostLoad
method is called by the JDO implementation after the
default fetch group
fields of your class have been loaded from the datastore.
Default fetch groups are explained in
Chapter 5, Metadata; for
now think of the default fetch group as all of the primitive
fields of the object. No other persistent fields can be
accessed in this method.
jdoPostLoad is often used to
initialize non-persistent fields whose values depend on
the values of persistent fields. An example of this is
presented below.
StoreCallback.jdoPreStore is
called just before the persistent values in your object
are flushed to the datastore. You can access all
persistent fields in this method.
jdoPreStore is the complement to
jdoPostLoad. While
jdoPostLoad is most often used to
initialize non-persistent values from persistent data,
jdoPreStore is usually used
to set persistent fields with information cached in
non-persistent ones. See the example below.
Note that the persistent identity of the object may not
have been assigned yet when this method is called.
The ClearCallback.jdoPreClear
method is called before the persistent fields of your
object are cleared.
JDO implementations clear the persistent state of objects
for several reasons, most of which will be covered later in
this document. You can use jdoPreClear
to clear non-persistent cached data and null
relations to other objects. You should not access the
values of persistent fields in this method.
DeleteCallback.jdoPreDelete is
called before an object transitions to the deleted state.
Access to persistent fields is valid within this method.
You might
use this method to cascade the deletion to related objects
based on complex criteria, or to perform other cleanup.
Unlike the PersistenceCapable interface,
you must implement the InstanceCallbacks
interfaces explicitly if you want to receive lifecycle callbacks.
![]() | Note |
|---|---|
The |
Example 4.3. Using Callback Interfaces
/**
* Example demonstrating the use of the InstanceCallbacks interface to
* persist a java.net.InetAddress and implement a privately-owned relation.
*/
public class Host
implements LoadCallback, StoreCallback, DeleteCallback
{
// the InetAddress field cannot be persisted directly by JDO, so we
// use the jdoPostLoad and jdoPreStore methods below to persist it
// indirectly through its host name string
private transient InetAddress address; // non-persistent
private String hostName; // persistent
// set of devices attached to this host
private Set devices = new HashSet ();
// setters, getters, and business logic omitted
public void jdoPostLoad ()
{
// form the InetAddress using the persistent host name
try
{
address = InetAddress.getByName (hostName);
}
catch (IOException ioe)
{
throw new JDOException ("Invalid host name: " + hostName, ioe);
}
}
public void jdoPreStore ()
{
// store the host name information based on the InetAddress values
hostName = address.getHostName ();
}
public void jdoPreDelete ()
{
// delete certain related devices when this object is deleted, based
// on business logic
PersistenceManager pm = JDOHelper.getPersistenceManager (this);
pm.deletePersistentAll (filterDependents (devices));
}
}

![]() | Note |
|---|---|
The |
Only persistent classes can implement the
InstanceCallbacks interfaces. This makes sense for
lifecycle actions such as caching internal state and deleting
dependent relations, but is clumsy for cross-cutting concerns like
logging and auditing. The lifecycle listener event framework solves
this problem by allowing non-persistent classes to subscribe
to lifecycle events. The framework consists of a common event
class, a common super-interface for event listeners, and several
individual listener interfaces. A concrete listener class can
implement any combination of listener interfaces.
InstanceLifecycleEvent: The
event class. The source of a lifecycle event is the
persistent object for which the event was triggered.
InstanceLifecycleListener:
Common base interface for all listener types.
InstanceLifecycleListener has no operations, but
gives a measure of type safety when adding listener objects
to a PersistenceManager or
PersistenceManagerFactory.
See Chapter 8, PersistenceManager and
Chapter 7, PersistenceManagerFactory.
LoadLifecycleListener:
Listens for persistent state loading events. Its
postLoad method is equivalent to
the InstanceCallbacks.jdoPostLoad
method described above.
StoreLifecycleListener:
Listens for persistent state flushes. Its
preStore method is equivalent to
the InstanceCallbacks.jdoPreStore
method described above. Its postStore
handler is invoked after the data for
the source object has been flushed to the database. Unlike
preStore, the source object is
guaranteed to have a persistent identity by the time
postStore is triggered.
ClearLifecycleListener:
Receives notifications when objects clear their persistent
state. Its preClear method is
equivalent to
InstanceCallbacks.jdoPreClear.
The postClear event is sent
just after the source object's state is cleared.
DeleteLifecycleListener:
Listens for object deletion events. Its
preDelete method is equivalent
to InstanceCallbacks.jdoPreDelete.
Its postDelete handler is triggered
after the source object has transitioned to the deleted
state. Access to persistent fields is not allowed in
postDelete.
CreateLifecycleListener:
The postCreate event is fired when
an object first transitions from unmanaged to
persistent-new, such as during a call to
PersistenceManager.makePersistent.
DirtyLifecycleListener:
Dirty events fire when an object is first modified
(in JDO parlance, becomes dirty) within a transaction.
The runtime invokes preDirty before
applying the change to the object, and postDirty
after applying the change.