Skip to content

Commit

Permalink
specify that an entity listener may have multiple callbacks of same type
Browse files Browse the repository at this point in the history
also write proper javadoc, and clean up the spec

see jakartaee#687

see jakartaee#684

Signed-off-by: Gavin King <gavin@hibernate.org>
  • Loading branch information
gavinking committed Nov 23, 2024
1 parent 1aac75c commit cebe51e
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 36 deletions.
56 changes: 54 additions & 2 deletions api/src/main/java/jakarta/persistence/EntityListeners.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,69 @@
* entity or mapped superclass. This annotation may be applied
* to an entity class or mapped superclass.
*
* <pre>
* &#64;Entity
* &#64;EntityListeners(BookObserver.class)
* class Book { ... }
* </pre>
*
* <p>The specified entity listener classes may have callback
* methods annotated {@link PrePersist}, {@link PreUpdate},
* {@link PreRemove}, {@link PostPersist}, {@link PostUpdate},
* and/or {@link PostRemove}.
* {@link PostRemove}, and/or {@link PostLoad}. A callback
* method defined by an entity listener class must have the
* signature {@code void method(E entity)} where {@code E} is
* a supertype of an entity class or mapped superclass to which
* the entity listener applies.
*
* <pre>
* class BookObserver {
*
* &#64;PostPersist
* void newBook(Book book) {
* ...
* }
*
* }
* </pre>
*
* <p>An entity listener class may have multiple callback
* methods for a given type of lifecycle event, but at most
* one callback method for a given type of event and given
* entity type.
*
* <pre>
* class Observer {
*
* // called only for Books
* &#64;PostPersist
* void newBook(Book book) {
* ...
* }
*
* // called only for Authors
* &#64;PostPersist
* void newAuthor(Author author) {
* ...
* }
*
* // called for any entity type to which the listener applies
* &#64;PostLoad
* void entityLoaded(Object entity) {
* ...
* }
*
* }
* </pre>
*
* @since 1.0
*/
@Target({TYPE})
@Retention(RUNTIME)
public @interface EntityListeners {

/** The callback listener classes */
/**
* The callback listener classes for the annotated entity.
*/
Class<?>[] value();
}
70 changes: 36 additions & 34 deletions spec/src/main/asciidoc/ch03-entity-operations.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,8 @@ describes the rules that apply to method invocation order in this case.

==== Entity Listeners

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

Entity listener classes in Jakarta EE
environments support dependency injection through the Contexts and
Expand Down Expand Up @@ -1327,21 +1328,22 @@ The same annotations (and XML elements) are used to declare:

The signatures of the callback methods differ between these two cases:

- a callback method defined by an entity class or mapped superclass has
the signature:
- a callback method defined by an entity class or mapped superclass must
have the signature:
+
void <METHOD>()
void method()
+
where `method` is a legal Java method name, but
- a callback method defined by an entity listener class has the signature:
+
void <METHOD>(S)
void method(E entity)
+
where `S` is any supertype of the entity class or mapped superclass to
which the entity listener is applied. At runtime, the argument to the
entity listener callback method is the entity instance for which the
callback method is being invoked.
where `method` is a legal Java method name, and `E` is any supertype of
an entity class or mapped superclass to which the entity listener applies.
At runtime, the argument to the entity listener callback method is the
entity instance for which the callback method is being invoked.

Callback methods can have public, private, protected, or package level
Callback methods can have `public`, `private`, `protected`, or package level
access, but must not be `static` or `final`.

The following annotations designate lifecycle event callback methods of
Expand Down Expand Up @@ -1370,6 +1372,14 @@ The following rules apply to lifecycle callback methods:
contextfootnote:[Note that this caution applies also to the actions of
objects that might be injected into an entity listener].

An entity or entity listener may have multiple lifecycle callback methods:

- an entity class may have at most one callback method for a given type
of lifecycle event, but
- an entity listener class may have multiple callback methods for a given
type of lifecycle event, but at most one callback method for a given
type of event and given entity type.

==== Semantics of the Life Cycle Callback Methods for Entities [[a2202]]

The `PrePersist` and `PreRemove` callback
Expand Down Expand Up @@ -1580,10 +1590,10 @@ public class CatListener2 {
If a `PostPersist` event occurs on an
instance of `Cat`, the following methods are called in order:

. postPersistPetListenerMethod
. postPersistCatListenerMethod
. postPersistCatListener2Method
. postPersistAnimal
. `postPersistPetListenerMethod`
. `postPersistCatListenerMethod`
. `postPersistCatListener2Method`
. `postPersistAnimal`

Assume that `SiameseCat` is defined as a
subclass of `Cat`:
Expand Down Expand Up @@ -1612,12 +1622,12 @@ public class SiameseCatListener {
If a `PostPersist` event occurs on an
instance of `SiameseCat`, the following methods are called in order:

. postPersistPetListenerMethod
. postPersistCatListenerMethod
. postPersistCatListener2Method
. postPersistSiameseCatListenerMethod
. postPersistAnimal
. postPersistSiameseCat
. `postPersistPetListenerMethod`
. `postPersistCatListenerMethod`
. `postPersistCatListener2Method`
. `postPersistSiameseCatListenerMethod`
. `postPersistAnimal`
. `postPersistSiameseCat`

Assume the definition of `SiameseCat` were instead:

Expand All @@ -1639,11 +1649,11 @@ In this case, the following methods would be
called in order, where `postPersistAnimal` is the `PostPersist` method
defined in the `SiameseCat` class:

. postPersistPetListenerMethod
. postPersistCatListenerMethod
. postPersistCatListener2Method
. postPersistSiameseCatListenerMethod
. postPersistAnimal
. `postPersistPetListenerMethod`
. `postPersistCatListenerMethod`
. `postPersistCatListener2Method`
. `postPersistSiameseCatListenerMethod`
. `postPersistAnimal`

==== Exceptions

Expand All @@ -1669,14 +1679,6 @@ class. The lifecycle listener methods are specified by using the
`pre-persist`, `post-persist`, `pre-remove`, `post-remove`,
`pre-update`, `post-update`, and/or `post-load` elements.

An entity listener class can define multiple
callback methods. However, at most one method of an entity listener
class can be designated as a pre-persist method, post-persist method,
pre-remove method, post-remove method, pre-update method, post-update
method, and/or post-load method, regardless of whether the XML
descriptor is used to define entity listeners or whether some
combination of annotations and XML descriptor elements is used.

===== Specification of the Binding of Entity Listener Classes to Entities

The `entity-listeners` subelement of the
Expand Down Expand Up @@ -1732,7 +1734,7 @@ specification <<a19498>>.

This specification supports the use of bean
validation for the automatic validation of entities upon the
pre-persist, pre-update, and pre-remove lifecycle validation events.
`pre-persist`, `pre-update`, and `pre-remove` lifecycle validation events.
These lifecycle validation events occur immediately after the point at
which all the `PrePersist`, `PreUpdate`, and `PreRemove` lifecycle
callback method invocations respectively have been completed, or
Expand Down

0 comments on commit cebe51e

Please sign in to comment.