Identify correct and incorrect statements or examples about Entity Listeners and Callback Methods, including: @PrePersist, @PostPersist, @PreRemove, @PostRemove, @PreUpdate, @PostUpdate, and @PostLoad, and when they are invoked.

[Note]

A method may be designated as a lifecycle callback method to receive notification of entity lifecycle events.

A lifecycle callback method may be defined on an entity class, a mapped superclass, or an entity listener class associated with an entity or mapped superclass. An entity listener class is a class whose methods are invoked in response to lifecycle events on an entity. ANY NUMBER of entity listener classes may be defined for an entity class or mapped superclass.

Default entity listeners - entity listeners that apply to all entities in the persistence unit - can be specified by means of the XML descriptor.

Lifecycle callback methods and entity listener classes are defined by means of metadata annotations or the XML descriptor. When annotations are used, one or more entity listener classes are denoted using the EntityListeners annotation on the entity class or mapped superclass. If multiple entity listeners are defined, the order in which they are invoked is determined by the order in which they are specified in the EntityListeners annotation. The XML descriptor may be used as an alternative to specify the invocation order of entity listeners or to override the order specified in metadata annotations.

Any subset or combination of annotations may be specified on an entity class, mapped superclass, or listener class. A single class MAY NOT have more than ONE lifecycle callback method for the same lifecycle event. The same method may be used for multiple callback events.

Multiple entity classes and mapped superclasses in an inheritance hierarchy may define listener classes and/or lifecycle callback methods directly on the class.

The entity listener class must have a public no-arg constructor.

Entity listeners are stateless. The lifecycle of an entity listener is unspecified.

The following rules apply to lifecycle callbacks:

When invoked from within a Java EE environment, the callback listeners for an entity share the enterprise naming context of the invoking component, and the entity callback methods are invoked in the transaction and security contexts of the calling component at the time at which the callback method is invoked.

Lifecycle Callback Methods

Entity lifecycle callback methods can be defined on an entity listener class and/or directly on an entity class or mapped superclass.

Lifecycle callback methods are annotated with annotations designating the callback events for which they are invoked or are mapped to the callback event using the XML descriptor.

The annotations used for callback methods on the entity class or mapped superclass and for callback methods on the entity listener class are the same. The signatures of individual methods, however, differ.

Callback methods defined on an entity class or mapped superclass have the following signature:


void <METHOD>()
					
					

When declaring callback methods on a persistent class, any method may be used which takes no arguments and is not shared with any property access fields. Multiple events can be assigned to a single method as well.

Below is an example of how to declare callback methods on persistent classes:


/**
 * Example persistent class declaring entity listener.
 */
@Entity
public class Magazine {

	@Transient 
	private byte[][] data;

	@ManyToMany
	private List<Photo> photos;

	@PostLoad
	public void convertPhotos() {
		data = new byte[photos.size()][];
		for (int i = 0; i < photos.size(); i++) {
			data[i] = photos.get(i).toByteArray();
		}	
	}

	@PreDelete
	public void logMagazineDeletion() {
		getLog().debug("deleting magazine containing" + photos.size() + " photos.");
	}
}

					

In an XML mapping file, we can define the same methods without annotations:


<entity class="Magazine">
	<pre-remove>logMagazineDeletion</pre-remove>
	<post-load>convertPhotos</post-load>
</entity>

					

Callback methods defined on an entity listener class have the following signature:


void <METHOD>(Object)
					
					

The Object argument is the entity instance for which the callback method is invoked. It may be declared as the actual entity type.

Mixing lifecycle event code into your persistent classes is not always ideal. It is often more elegant to handle cross-cutting lifecycle events in a non-persistent listener class. JPA allows for this, requiring only that listener classes have a public no-arg constructor. Like persistent classes, your listener classes can consume any number of callbacks. The callback methods must take in a single java.lang.Object argument which represents the persistent object that triggered the event.

Entities can enumerate listeners using the EntityListeners annotation. This annotation takes an array of listener classes as its value.

Below is an example of how to declare an entity and its corresponding listener classes:

/**
 * Example persistent class declaring entity listener.
 */
@Entity
@EntityListeners({ MagazineLogger.class, ... })
public class Magazine {	
	...
}
					
/**
 * Example entity listener.
 */
public class MagazineLogger {

	@PostPersist
	public void logAddition(Object pc) {
		getLog ().debug ("Added new magazine:" + ((Magazine) pc).getTitle ());
	}

	@PreRemove
	public void logDeletion(Object pc) {
		getLog().debug("Removing from circulation:" + ((Magazine) pc).getTitle());
	}
}
					

In XML, we define both the listeners and their callback methods as so:


<entity class="Magazine">
	<entity-listeners>
		<entity-listener class="MagazineLogger">
			<post-persist>logAddition</post-persist>
			<pre-remove>logDeletion</pre-remove>
		</entity-listener>
	</entity-listeners>
</entity>
					
					

The callback methods can have public, private, protected, or package level access, but MUST NOT be static or final.

The following annotations are defined to designate lifecycle event callback methods of the corresponding types:

Entity Lifecycle Callback Event Annotations

Semantics of the Life Cycle Callback Methods for Entities

The @PrePersist and @PreRemove callback methods are invoked for a given entity BEFORE the respective EntityManager persist and remove operations for that entity are executed. For entities to which the merge operation has been applied and causes the creation of newly managed instances, the @PrePersist callback methods will be invoked for the managed instance AFTER the entity state has been copied to it. These @PrePersist and @PreRemove callbacks will also be invoked on all entities to which these operations are cascaded. The @PrePersist and @PreRemove methods will always be invoked as part of the synchronous persist, merge, and remove operations.

The @PostPersist and @PostRemove callback methods are invoked for an entity AFTER the entity has been made persistent or removed. These callbacks will also be invoked on all entities to which these operations are cascaded. The @PostPersist and @PostRemove methods will be invoked AFTER the database INSERT and DELETE operations respectively. These database operations may occur directly after the persist, merge, or remove operations have been invoked or they may occur directly after a flush operation has occurred (which may be at the end of the transaction). Generated primary key values are available in the @PostPersist method.

The @PreUpdate and @PostUpdate callbacks occur BEFORE and AFTER the database UPDATE operations to entity data respectively. These database operations may occur at the time the entity state is updated or they may occur at the time state is flushed to the database (which may be at the end of the transaction).

The @PostLoad method for an entity is invoked AFTER the entity has been loaded into the current persistence context from the database or after the refresh operation has been applied to it. The @PostLoad method is invoked before a query result is returned or accessed or before an association is traversed.

Multiple Lifecycle Callback Methods for an Entity Lifecycle Event

If multiple callback methods are defined for an entity lifecycle event, the ordering of the invocation of these methods is as follows.

Default listeners, if any, are invoked first, in the order specified in the XML descriptor. Default listeners apply to all entities in the persistence unit, unless explicitly excluded by means of the ExcludeDefaultListeners annotation or exclude-default-listeners XML element.

The lifecycle callback methods defined on the entity listener classes for an entity class or mapped superclass are invoked in the same order as the specification of the entity listener classes in the EntityListeners annotation.

If MULTIPLE classes in an inheritance hierarchy - entity classes and/or mapped superclasses - define entity listeners, the listeners defined for a SUPERCLASS are invoked BEFORE the listeners defined for its subclasses in this order. The ExcludeSuperclassListeners annotation or exclude-superclass-listeners XML element may be applied to an entity class or mapped superclass to exclude the invocation of the listeners defined by the entity listener classes for the superclasses of the entity or mapped superclass. The excluded listeners are excluded from the class to which the ExcludeSuperclassListeners annotation or element has been specified and its subclasses. The ExcludeSuperclassListeners annotation (or exclude-superclass-listeners XML element) DOES NOT cause default entity listeners to be excluded from invocation.

If a lifecycle callback method for the same lifecycle event is also specified on the entity class and/or one or more of its entity or mapped superclasses, the callback methods on the entity class and/or superclasses are invoked AFTER the other lifecycle callback methods, most general superclass first. A class is permitted to override an inherited callback method of the same callback type, and in this case, the overridden method is NOT invoked.

Callback methods are invoked by the persistence provider runtime in the order specified. If the callback method execution terminates normally, the persistence provider runtime then invokes the next callback method, if any.

The XML descriptor may be used to OVERRIDE the lifecycle callback method invocation order specified in annotations.

Example:

@Entity
public class Animal {
	....
	@PostPersist
	protected void postPersistAnimal() {
		....
	}
}
					
@Entity
@EntityListeners(PetListener.class)
public class Pet extends Animal {
	...
}
					
@Entity
@EntityListeners({CatListener.class, CatListener2.class})
public class Cat extends Pet {
	...
}
					
public class PetListener {
	@PostPersist
	protected void postPersistPetListenerMethod(Object pet) {
		...
	}
}
					
public class CatListener {
	@PostPersist
	protected void postPersistCatListenerMethod(Object cat) {
		...
	}
}
					
public class CatListener2 {
	@PostPersist
	protected void postPersistCatListener2Method(Object cat) {
		...
	}
}
					

CASE 1: If a @PostPersist event occurs on an instance of Cat, the following methods are called in order:

  1. postPersistPetListenerMethod

  2. postPersistCatListenerMethod

  3. postPersistCatListener2Method

  4. postPersistAnimal

Assume that SiameseCat is defined as a subclass of Cat:

@EntityListeners(SiameseCatListener.class)
@Entity
public class SiameseCat extends Cat {
	...
	@PostPersist
	protected void postPersistSiameseCat() {
		...
	}
}
					
public class SiameseCatListener {
	@PostPersist
	protected void postPersistSiameseCatListenerMethod(Object cat) {
		...
	}
}					
					

CASE 2: If a @PostPersist event occurs on an instance of SiameseCat, the following methods are called in order:

  1. postPersistPetListenerMethod

  2. postPersistCatListenerMethod

  3. postPersistCatListener2Method

  4. postPersistSiameseCatListenerMethod

  5. postPersistAnimal

  6. postPersistSiameseCat

Assume the definition of SiameseCat were instead:

@EntityListeners(SiameseCatListener.class)
@Entity
public class SiameseCat extends Cat {
	...
	@PostPersist
	protected void postPersistAnimal() {
		...
	}
}
					

CASE 3: In this case, the following methods would be called in order, where postPersistAnimal is the @PostPersist method defined in the SiameseCat class:

  1. postPersistPetListenerMethod

  2. postPersistCatListenerMethod

  3. postPersistCatListener2Method

  4. postPersistSiameseCatListenerMethod

  5. postPersistAnimal

Entity listener methods are invoked in a specific order when a given event is fired. So-called default listeners are invoked first: these are listeners which have been defined in a package annotation or in the root element of XML mapping files. Next, entity listeners are invoked in the order of the inheritance hierarchy, with superclass listeners being invoked before subclass listeners. Finally, if an entity has multiple listeners for the same event, the listeners are invoked in declaration order.

You can exclude default listeners and listeners defined in superclasses from the invocation chain through the use of two class-level annotations:

Professional hosting     Belorussian informational portal         Free SCWCD 1.4 Study Guide     Free SCDJWS 1.4 Study Guide     SCDJWS 1.4 Quiz     Free IBM Certified Associate Developer Study Guide     IBM Test 000-287. Enterprise Application Development with IBM WebSphere Studio, V5.0 Study Guide     Free Mock Exam Engine