From 2456ae4ea94e36d352478c480b1445c1bd576fb7 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 24 Oct 2024 20:12:30 +0200 Subject: [PATCH 01/24] first rough proposal for events see #373 Signed-off-by: Gavin King --- .../jakarta/data/event/LifecycleEvent.java | 29 ++++++++++++++++++ .../jakarta/data/event/PostDeleteEvent.java | 30 +++++++++++++++++++ .../jakarta/data/event/PostInsertEvent.java | 30 +++++++++++++++++++ .../jakarta/data/event/PostUpdateEvent.java | 30 +++++++++++++++++++ .../jakarta/data/event/PreDeleteEvent.java | 30 +++++++++++++++++++ .../jakarta/data/event/PreInsertEvent.java | 30 +++++++++++++++++++ .../jakarta/data/event/PreUpdateEvent.java | 30 +++++++++++++++++++ .../java/jakarta/data/repository/Delete.java | 5 ++++ .../java/jakarta/data/repository/Insert.java | 5 ++++ .../java/jakarta/data/repository/Update.java | 5 ++++ spec/src/main/asciidoc/jakarta-ee.adoc | 7 +++++ 11 files changed, 231 insertions(+) create mode 100644 api/src/main/java/jakarta/data/event/LifecycleEvent.java create mode 100644 api/src/main/java/jakarta/data/event/PostDeleteEvent.java create mode 100644 api/src/main/java/jakarta/data/event/PostInsertEvent.java create mode 100644 api/src/main/java/jakarta/data/event/PostUpdateEvent.java create mode 100644 api/src/main/java/jakarta/data/event/PreDeleteEvent.java create mode 100644 api/src/main/java/jakarta/data/event/PreInsertEvent.java create mode 100644 api/src/main/java/jakarta/data/event/PreUpdateEvent.java diff --git a/api/src/main/java/jakarta/data/event/LifecycleEvent.java b/api/src/main/java/jakarta/data/event/LifecycleEvent.java new file mode 100644 index 00000000..6ceb08e1 --- /dev/null +++ b/api/src/main/java/jakarta/data/event/LifecycleEvent.java @@ -0,0 +1,29 @@ +package jakarta.data.event; + +/** + *

Abstract supertype of events relating to lifecycle methods.

+ *

In Jakarta EE, a bean may observe such events via CDI:

+ *
+ * void onInsertBook(@Observes PostInsertEvent<Book> bookInsertion) {
+ *     Book book = bookInsertion.entity();
+ *     ...
+ * }
+ * 
+ * + * @param the entity type + */ +public abstract class LifecycleEvent { + private final E entity; + + public LifecycleEvent(E entity) { + this.entity = entity; + } + + /** + * The entity instance which was passed as an argument to + * the lifecycle method. + */ + public E entity() { + return entity; + } +} diff --git a/api/src/main/java/jakarta/data/event/PostDeleteEvent.java b/api/src/main/java/jakarta/data/event/PostDeleteEvent.java new file mode 100644 index 00000000..0d1d65e1 --- /dev/null +++ b/api/src/main/java/jakarta/data/event/PostDeleteEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data.event; + +/** + * An event that occurs when an {@link jakarta.data.repository.Delete} + * method is called, and after the record was deleted from the datastore. + * + * @param the entity type + */ +public class PostDeleteEvent extends LifecycleEvent { + public PostDeleteEvent(E entity) { + super(entity); + } +} diff --git a/api/src/main/java/jakarta/data/event/PostInsertEvent.java b/api/src/main/java/jakarta/data/event/PostInsertEvent.java new file mode 100644 index 00000000..d8668936 --- /dev/null +++ b/api/src/main/java/jakarta/data/event/PostInsertEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data.event; + +/** + * An event that occurs when an {@link jakarta.data.repository.Insert} + * method is called, and after the record was inserted into the datastore. + * + * @param the entity type + */ +public class PostInsertEvent extends LifecycleEvent { + public PostInsertEvent(E entity) { + super(entity); + } +} diff --git a/api/src/main/java/jakarta/data/event/PostUpdateEvent.java b/api/src/main/java/jakarta/data/event/PostUpdateEvent.java new file mode 100644 index 00000000..173f8281 --- /dev/null +++ b/api/src/main/java/jakarta/data/event/PostUpdateEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data.event; + +/** + * An event that occurs when an {@link jakarta.data.repository.Update} + * method is called, and after the entity was updated in the datastore. + * + * @param the entity type + */ +public class PostUpdateEvent extends LifecycleEvent { + public PostUpdateEvent(E entity) { + super(entity); + } +} diff --git a/api/src/main/java/jakarta/data/event/PreDeleteEvent.java b/api/src/main/java/jakarta/data/event/PreDeleteEvent.java new file mode 100644 index 00000000..0e4668a3 --- /dev/null +++ b/api/src/main/java/jakarta/data/event/PreDeleteEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data.event; + +/** + * An event that occurs when an {@link jakarta.data.repository.Delete} + * method is called, but before the record is deleted from the datastore. + * + * @param the entity type + */ +public class PreDeleteEvent extends LifecycleEvent { + public PreDeleteEvent(E entity) { + super(entity); + } +} diff --git a/api/src/main/java/jakarta/data/event/PreInsertEvent.java b/api/src/main/java/jakarta/data/event/PreInsertEvent.java new file mode 100644 index 00000000..68cfabed --- /dev/null +++ b/api/src/main/java/jakarta/data/event/PreInsertEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data.event; + +/** + * An event that occurs when an {@link jakarta.data.repository.Insert} + * method is called, but before the record is inserted into the datastore. + * + * @param the entity type + */ +public class PreInsertEvent extends LifecycleEvent { + public PreInsertEvent(E entity) { + super(entity); + } +} diff --git a/api/src/main/java/jakarta/data/event/PreUpdateEvent.java b/api/src/main/java/jakarta/data/event/PreUpdateEvent.java new file mode 100644 index 00000000..3e4b5ada --- /dev/null +++ b/api/src/main/java/jakarta/data/event/PreUpdateEvent.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package jakarta.data.event; + +/** + * An event that occurs when an {@link jakarta.data.repository.Update} + * method is called, but before the entity is updated in the datastore. + * + * @param the entity type + */ +public class PreUpdateEvent extends LifecycleEvent { + public PreUpdateEvent(E entity) { + super(entity); + } +} diff --git a/api/src/main/java/jakarta/data/repository/Delete.java b/api/src/main/java/jakarta/data/repository/Delete.java index f2d1a8e3..c3ca9335 100644 --- a/api/src/main/java/jakarta/data/repository/Delete.java +++ b/api/src/main/java/jakarta/data/repository/Delete.java @@ -59,6 +59,11 @@ * if the entity with a matching identifier does not have a matching version, the annotated method must raise * {@link jakarta.data.exceptions.OptimisticLockingFailureException}. *

+ *

+ * An event of type {@link jakarta.data.event.PreDeleteEvent} must be raised by the annotated method before the record + * is deleted. An event of type {@link jakarta.data.event.PostDeleteEvent} must be raised by the annotated method after + * the record was successfully deleted. + *

* *

Alternatively, the {@code Delete} annotation may be used to annotate a repository method with no parameter of * entity type. Then the repository method is interpreted as a parameter-based automatic query method. The entity type diff --git a/api/src/main/java/jakarta/data/repository/Insert.java b/api/src/main/java/jakarta/data/repository/Insert.java index 5112adf7..e40f961f 100644 --- a/api/src/main/java/jakarta/data/repository/Insert.java +++ b/api/src/main/java/jakarta/data/repository/Insert.java @@ -66,6 +66,11 @@ * then the annotated method must raise {@link jakarta.data.exceptions.EntityExistsException}. * If the database follows the BASE model, or uses an append model to write data, this exception is not thrown. *

+ *

+ * An event of type {@link jakarta.data.event.PreInsertEvent} must be raised by the annotated method before the record + * is inserted. An event of type {@link jakarta.data.event.PostInsertEvent} must be raised by the annotated method after + * the record was successfully inserted. + *

*

Annotations such as {@code @Find}, {@code @Query}, {@code @Insert}, {@code @Update}, {@code @Delete}, and * {@code @Save} are mutually-exclusive. A given method of a repository interface may have at most one {@code @Find} * annotation, lifecycle annotation, or query annotation. diff --git a/api/src/main/java/jakarta/data/repository/Update.java b/api/src/main/java/jakarta/data/repository/Update.java index 3045ec97..f8315ef0 100644 --- a/api/src/main/java/jakarta/data/repository/Update.java +++ b/api/src/main/java/jakarta/data/repository/Update.java @@ -67,6 +67,11 @@ * If the database follows the BASE model, or uses an append model to write data, the annotated method behaves the same * as the {@code @Insert} method. *

+ *

+ * An event of type {@link jakarta.data.event.PreUpdateEvent} must be raised by the annotated method before the record + * is updated. An event of type {@link jakarta.data.event.PostUpdateEvent} must be raised by the annotated method after + * the record was successfully updated. + *

*

Annotations such as {@code @Find}, {@code @Query}, {@code @Insert}, {@code @Update}, {@code @Delete}, and * {@code @Save} are mutually-exclusive. A given method of a repository interface may have at most one {@code @Find} * annotation, lifecycle annotation, or query annotation. diff --git a/spec/src/main/asciidoc/jakarta-ee.adoc b/spec/src/main/asciidoc/jakarta-ee.adoc index bc51e27b..8d2b6da9 100644 --- a/spec/src/main/asciidoc/jakarta-ee.adoc +++ b/spec/src/main/asciidoc/jakarta-ee.adoc @@ -67,6 +67,8 @@ This section discusses interoperability with related Jakarta EE footnote:[Jakart Contexts and Dependency Injection footnote:[Jakarta Contexts and Dependency Injection 4.1, https://jakarta.ee/specifications/cdi/4.1/] (CDI) is a specification in the Jakarta EE Core profile that provides a powerful and flexible dependency injection framework for Java applications. CDI provides a programming model based around decoupled components with container-managed lifecycles and container-injected dependencies, enabling loose coupling and promoting modular and reusable code. +==== CDI Dependency Injection + In the Jakarta EE environment, CDI allows implementations of Jakarta Data repositories to be made available for injection via the `@Inject` annotation. The following example illustrates this integration: @@ -115,6 +117,11 @@ This fragment shows how the application might request injection of a `CarReposit This integration between CDI and Jakarta Data allows for seamless management of repository instances within Jakarta EE applications. +==== CDI Events + +A repository implementation may raise CDI events. +In the Jakarta EE environment, the repository implementation is required the raise the event types defined in the package `jakarta.data.event` when lifecycle methods annotated `@Insert`, `@Update`, or `@Delete` are invoked, as specified by the API documentation of these annotations. + ==== CDI Extensions for Jakarta Data providers In environments where CDI Full or CDI Lite is available, Jakarta Data providers can make use of a CDI extension--an implementation of `jakarta.enterprise.inject.spi.Extension` or `jakarta.enterprise.inject.build.compatible.spi.BuildCompatibleExtension`--to discover interfaces annotated with `@Repository` and make their implementations available for injection. From 3deeca1c31e306ce096099525965fccf8df125e9 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:44:24 +0200 Subject: [PATCH 02/24] Update api/src/main/java/jakarta/data/event/LifecycleEvent.java Co-authored-by: Nathan Rauh --- .../java/jakarta/data/event/LifecycleEvent.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/api/src/main/java/jakarta/data/event/LifecycleEvent.java b/api/src/main/java/jakarta/data/event/LifecycleEvent.java index 6ceb08e1..459d3c2a 100644 --- a/api/src/main/java/jakarta/data/event/LifecycleEvent.java +++ b/api/src/main/java/jakarta/data/event/LifecycleEvent.java @@ -1,3 +1,20 @@ +/* + * Copyright (c) 2024 Contributors to the Eclipse Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ package jakarta.data.event; /** From fd3d56f6a63f5469c443a555ad2e05fd9991aacd Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:46:00 +0200 Subject: [PATCH 03/24] Update api/src/main/java/jakarta/data/event/PostDeleteEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostDeleteEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PostDeleteEvent.java b/api/src/main/java/jakarta/data/event/PostDeleteEvent.java index 0d1d65e1..dfce8f5d 100644 --- a/api/src/main/java/jakarta/data/event/PostDeleteEvent.java +++ b/api/src/main/java/jakarta/data/event/PostDeleteEvent.java @@ -19,7 +19,7 @@ /** * An event that occurs when an {@link jakarta.data.repository.Delete} - * method is called, and after the record was deleted from the datastore. + * lifecycle method is called, and after each record is deleted from the datastore. * * @param the entity type */ From 53be717e2c94ddef04fcb02d2cea1bab962fe0b7 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:46:17 +0200 Subject: [PATCH 04/24] Update api/src/main/java/jakarta/data/event/PostInsertEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostInsertEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PostInsertEvent.java b/api/src/main/java/jakarta/data/event/PostInsertEvent.java index d8668936..7378771b 100644 --- a/api/src/main/java/jakarta/data/event/PostInsertEvent.java +++ b/api/src/main/java/jakarta/data/event/PostInsertEvent.java @@ -19,7 +19,7 @@ /** * An event that occurs when an {@link jakarta.data.repository.Insert} - * method is called, and after the record was inserted into the datastore. + * lifecycle method is called, and after each record is inserted into the datastore. * * @param the entity type */ From 2c450347a24ebeee7779975020409d4404281af1 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:46:29 +0200 Subject: [PATCH 05/24] Update api/src/main/java/jakarta/data/event/PreUpdateEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PreUpdateEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PreUpdateEvent.java b/api/src/main/java/jakarta/data/event/PreUpdateEvent.java index 3e4b5ada..59c22bae 100644 --- a/api/src/main/java/jakarta/data/event/PreUpdateEvent.java +++ b/api/src/main/java/jakarta/data/event/PreUpdateEvent.java @@ -19,7 +19,7 @@ /** * An event that occurs when an {@link jakarta.data.repository.Update} - * method is called, but before the entity is updated in the datastore. + * lifecycle method is called, but before each entity is updated in the datastore. * * @param the entity type */ From cd98c235ef272524b699c80eed7c295e90f9befb Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:46:58 +0200 Subject: [PATCH 06/24] Update api/src/main/java/jakarta/data/event/PostUpdateEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostUpdateEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PostUpdateEvent.java b/api/src/main/java/jakarta/data/event/PostUpdateEvent.java index 173f8281..b06d49eb 100644 --- a/api/src/main/java/jakarta/data/event/PostUpdateEvent.java +++ b/api/src/main/java/jakarta/data/event/PostUpdateEvent.java @@ -19,7 +19,7 @@ /** * An event that occurs when an {@link jakarta.data.repository.Update} - * method is called, and after the entity was updated in the datastore. + * lifecycle method is called, and after each entity is updated in the datastore. * * @param the entity type */ From 5d767d5d1a5004d411accf0449c21e943da543c2 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:47:31 +0200 Subject: [PATCH 07/24] Update api/src/main/java/jakarta/data/repository/Update.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/repository/Update.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/jakarta/data/repository/Update.java b/api/src/main/java/jakarta/data/repository/Update.java index f8315ef0..cff37065 100644 --- a/api/src/main/java/jakarta/data/repository/Update.java +++ b/api/src/main/java/jakarta/data/repository/Update.java @@ -68,9 +68,9 @@ * as the {@code @Insert} method. *

*

- * An event of type {@link jakarta.data.event.PreUpdateEvent} must be raised by the annotated method before the record - * is updated. An event of type {@link jakarta.data.event.PostUpdateEvent} must be raised by the annotated method after - * the record was successfully updated. + * An event of type {@link jakarta.data.event.PreUpdateEvent} must be raised by the annotated lifecycle + * method before each record is updated. An event of type {@link jakarta.data.event.PostUpdateEvent} + * must be raised by the annotated lifecycle method after each record is successfully updated. *

*

Annotations such as {@code @Find}, {@code @Query}, {@code @Insert}, {@code @Update}, {@code @Delete}, and * {@code @Save} are mutually-exclusive. A given method of a repository interface may have at most one {@code @Find} From 206746d764755d337a8084067aef14fd3771607c Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:47:52 +0200 Subject: [PATCH 08/24] Update api/src/main/java/jakarta/data/event/PreDeleteEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PreDeleteEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PreDeleteEvent.java b/api/src/main/java/jakarta/data/event/PreDeleteEvent.java index 0e4668a3..9bf47130 100644 --- a/api/src/main/java/jakarta/data/event/PreDeleteEvent.java +++ b/api/src/main/java/jakarta/data/event/PreDeleteEvent.java @@ -19,7 +19,7 @@ /** * An event that occurs when an {@link jakarta.data.repository.Delete} - * method is called, but before the record is deleted from the datastore. + * lifecycle method is called, but before each record is deleted from the datastore. * * @param the entity type */ From 290be6b574d5e988a8df6d8f1831984f1c0d9fdb Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:48:12 +0200 Subject: [PATCH 09/24] Update api/src/main/java/jakarta/data/repository/Insert.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/repository/Insert.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/jakarta/data/repository/Insert.java b/api/src/main/java/jakarta/data/repository/Insert.java index e40f961f..7dc8a597 100644 --- a/api/src/main/java/jakarta/data/repository/Insert.java +++ b/api/src/main/java/jakarta/data/repository/Insert.java @@ -67,9 +67,9 @@ * If the database follows the BASE model, or uses an append model to write data, this exception is not thrown. *

*

- * An event of type {@link jakarta.data.event.PreInsertEvent} must be raised by the annotated method before the record - * is inserted. An event of type {@link jakarta.data.event.PostInsertEvent} must be raised by the annotated method after - * the record was successfully inserted. + * An event of type {@link jakarta.data.event.PreInsertEvent} must be raised by the annotated lifecycle + * method before each record is inserted. An event of type {@link jakarta.data.event.PostInsertEvent} + * must be raised by the annotated lifecycle method after each record is successfully inserted. *

*

Annotations such as {@code @Find}, {@code @Query}, {@code @Insert}, {@code @Update}, {@code @Delete}, and * {@code @Save} are mutually-exclusive. A given method of a repository interface may have at most one {@code @Find} From e4eae356ea1e4da722dacd73814e554ca80d7f1f Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:48:26 +0200 Subject: [PATCH 10/24] Update api/src/main/java/jakarta/data/repository/Delete.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/repository/Delete.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/jakarta/data/repository/Delete.java b/api/src/main/java/jakarta/data/repository/Delete.java index c3ca9335..4e936909 100644 --- a/api/src/main/java/jakarta/data/repository/Delete.java +++ b/api/src/main/java/jakarta/data/repository/Delete.java @@ -60,9 +60,9 @@ * {@link jakarta.data.exceptions.OptimisticLockingFailureException}. *

*

- * An event of type {@link jakarta.data.event.PreDeleteEvent} must be raised by the annotated method before the record - * is deleted. An event of type {@link jakarta.data.event.PostDeleteEvent} must be raised by the annotated method after - * the record was successfully deleted. + * An event of type {@link jakarta.data.event.PreDeleteEvent} must be raised by the annotated lifecycle + * method before each record is deleted. An event of type {@link jakarta.data.event.PostDeleteEvent} + * must be raised by the annotated lifecycle method after each record is successfully deleted. *

* *

Alternatively, the {@code Delete} annotation may be used to annotate a repository method with no parameter of From 7ec73598595dc1fe48e9173aba1daccf8a729f6e Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 01:48:43 +0200 Subject: [PATCH 11/24] Update api/src/main/java/jakarta/data/event/PreInsertEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PreInsertEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PreInsertEvent.java b/api/src/main/java/jakarta/data/event/PreInsertEvent.java index 68cfabed..bc4ec005 100644 --- a/api/src/main/java/jakarta/data/event/PreInsertEvent.java +++ b/api/src/main/java/jakarta/data/event/PreInsertEvent.java @@ -19,7 +19,7 @@ /** * An event that occurs when an {@link jakarta.data.repository.Insert} - * method is called, but before the record is inserted into the datastore. + * lifecycle method is called, but before each record is inserted into the datastore. * * @param the entity type */ From 3f5bad50c33bbff9251db5ca8d77da4620414172 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Fri, 25 Oct 2024 20:20:22 +0200 Subject: [PATCH 12/24] Update spec/src/main/asciidoc/jakarta-ee.adoc Co-authored-by: Kyle Aure --- spec/src/main/asciidoc/jakarta-ee.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/src/main/asciidoc/jakarta-ee.adoc b/spec/src/main/asciidoc/jakarta-ee.adoc index 8d2b6da9..c08ce8e9 100644 --- a/spec/src/main/asciidoc/jakarta-ee.adoc +++ b/spec/src/main/asciidoc/jakarta-ee.adoc @@ -120,7 +120,7 @@ This integration between CDI and Jakarta Data allows for seamless management of ==== CDI Events A repository implementation may raise CDI events. -In the Jakarta EE environment, the repository implementation is required the raise the event types defined in the package `jakarta.data.event` when lifecycle methods annotated `@Insert`, `@Update`, or `@Delete` are invoked, as specified by the API documentation of these annotations. +In the Jakarta EE environment, the repository implementation is required to raise the event types defined in the package `jakarta.data.event` when lifecycle methods annotated `@Insert`, `@Update`, or `@Delete` are invoked, as specified by the API documentation of these annotations. ==== CDI Extensions for Jakarta Data providers From 71eab887fc2ad55e786f172f95e123aa3eb47e6e Mon Sep 17 00:00:00 2001 From: Gavin King Date: Wed, 20 Nov 2024 20:44:05 +0100 Subject: [PATCH 13/24] set expectations around the entity() method of LifecycleEvent Signed-off-by: Gavin King --- .../jakarta/data/event/LifecycleEvent.java | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/jakarta/data/event/LifecycleEvent.java b/api/src/main/java/jakarta/data/event/LifecycleEvent.java index 459d3c2a..5d3ae1bc 100644 --- a/api/src/main/java/jakarta/data/event/LifecycleEvent.java +++ b/api/src/main/java/jakarta/data/event/LifecycleEvent.java @@ -37,8 +37,32 @@ public LifecycleEvent(E entity) { } /** - * The entity instance which was passed as an argument to - * the lifecycle method. + * The entity which is being processed by the lifecycle method. + *

    + *
  • For a {@code Pre} event, this is always the instance + * which was passed as an argument to the lifecycle + * method, and its state reflects the state of the + * entity before execution of the lifecycle method.
  • + *
  • For a {@code Post} event, it may or may not be + * identical to the object passed as an argument + * to the lifecycle method, and it may or may not be + * identical to the instance returned by the lifecycle + * method, if any. If the state of the entity changes + * as a result of execution of the lifecycle method, + * those changes may or may not be reflected in the + * entity returned by this method.
  • + *
+ *

+ * Thus, a portable application should not assume that the + * state of the entity in a {@code Post} event faithfully + * reflects the current state of the corresponding record + * in the database. + *

+ * A portable application must not mutate the state of the + * entity instance returned by this method. If the state + * of the entity instance is mutated during while event + * listeners are being notified, then the resulting + * behavior is undefined and unportable. */ public E entity() { return entity; From 32e548a495757c6f804f546065f2be2f6862902a Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:28:30 +0100 Subject: [PATCH 14/24] Update api/src/main/java/jakarta/data/event/PreUpdateEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PreUpdateEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PreUpdateEvent.java b/api/src/main/java/jakarta/data/event/PreUpdateEvent.java index 59c22bae..4e9e8ab5 100644 --- a/api/src/main/java/jakarta/data/event/PreUpdateEvent.java +++ b/api/src/main/java/jakarta/data/event/PreUpdateEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 5ca2a9ded5b93a3894815a2cc6b6c774e23149ec Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:29:14 +0100 Subject: [PATCH 15/24] Update api/src/main/java/jakarta/data/event/PostDeleteEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostDeleteEvent.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/src/main/java/jakarta/data/event/PostDeleteEvent.java b/api/src/main/java/jakarta/data/event/PostDeleteEvent.java index dfce8f5d..2d76c7db 100644 --- a/api/src/main/java/jakarta/data/event/PostDeleteEvent.java +++ b/api/src/main/java/jakarta/data/event/PostDeleteEvent.java @@ -18,8 +18,8 @@ package jakarta.data.event; /** - * An event that occurs when an {@link jakarta.data.repository.Delete} - * lifecycle method is called, and after each record is deleted from the datastore. + * An event that occurs when a {@link jakarta.data.repository.Delete} + * lifecycle method is called, after each record is deleted from the datastore. * * @param the entity type */ From 965aa3ab6c7576052b88a6fb3d7906a79e006ed0 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:29:43 +0100 Subject: [PATCH 16/24] Update api/src/main/java/jakarta/data/event/PostDeleteEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostDeleteEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PostDeleteEvent.java b/api/src/main/java/jakarta/data/event/PostDeleteEvent.java index 2d76c7db..8e83ae75 100644 --- a/api/src/main/java/jakarta/data/event/PostDeleteEvent.java +++ b/api/src/main/java/jakarta/data/event/PostDeleteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From bc49d2d5d130d51dcba96ac0908b9f57afa6b0fc Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:30:00 +0100 Subject: [PATCH 17/24] Update api/src/main/java/jakarta/data/event/PostInsertEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostInsertEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PostInsertEvent.java b/api/src/main/java/jakarta/data/event/PostInsertEvent.java index 7378771b..c95ed1ae 100644 --- a/api/src/main/java/jakarta/data/event/PostInsertEvent.java +++ b/api/src/main/java/jakarta/data/event/PostInsertEvent.java @@ -19,7 +19,7 @@ /** * An event that occurs when an {@link jakarta.data.repository.Insert} - * lifecycle method is called, and after each record is inserted into the datastore. + * lifecycle method is called, after each record is inserted into the datastore. * * @param the entity type */ From 64492bd5dc2f3496d7ee486bc986f3fd9ed0bcc0 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:30:13 +0100 Subject: [PATCH 18/24] Update api/src/main/java/jakarta/data/event/PreInsertEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PreInsertEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PreInsertEvent.java b/api/src/main/java/jakarta/data/event/PreInsertEvent.java index bc4ec005..d4da4c15 100644 --- a/api/src/main/java/jakarta/data/event/PreInsertEvent.java +++ b/api/src/main/java/jakarta/data/event/PreInsertEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 68d88a3045c3400578c75b66b77302335543ba4d Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:30:32 +0100 Subject: [PATCH 19/24] Update api/src/main/java/jakarta/data/event/PreDeleteEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PreDeleteEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PreDeleteEvent.java b/api/src/main/java/jakarta/data/event/PreDeleteEvent.java index 9bf47130..1612436f 100644 --- a/api/src/main/java/jakarta/data/event/PreDeleteEvent.java +++ b/api/src/main/java/jakarta/data/event/PreDeleteEvent.java @@ -18,7 +18,7 @@ package jakarta.data.event; /** - * An event that occurs when an {@link jakarta.data.repository.Delete} + * An event that occurs when a {@link jakarta.data.repository.Delete} * lifecycle method is called, but before each record is deleted from the datastore. * * @param the entity type From 9c0d3c4101873680010c2f691959393ea13feed5 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:30:43 +0100 Subject: [PATCH 20/24] Update api/src/main/java/jakarta/data/event/PostInsertEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostInsertEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PostInsertEvent.java b/api/src/main/java/jakarta/data/event/PostInsertEvent.java index c95ed1ae..c81a4a16 100644 --- a/api/src/main/java/jakarta/data/event/PostInsertEvent.java +++ b/api/src/main/java/jakarta/data/event/PostInsertEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 40bbaabc30f7d5d0b0b75e9565603e362b17c02d Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:31:04 +0100 Subject: [PATCH 21/24] Update api/src/main/java/jakarta/data/event/PostUpdateEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostUpdateEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PostUpdateEvent.java b/api/src/main/java/jakarta/data/event/PostUpdateEvent.java index b06d49eb..93d70760 100644 --- a/api/src/main/java/jakarta/data/event/PostUpdateEvent.java +++ b/api/src/main/java/jakarta/data/event/PostUpdateEvent.java @@ -19,7 +19,7 @@ /** * An event that occurs when an {@link jakarta.data.repository.Update} - * lifecycle method is called, and after each entity is updated in the datastore. + * lifecycle method is called, after each entity is updated in the datastore. * * @param the entity type */ From 19f408f2a35de61fc03824ce25c1746d4048853b Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:31:21 +0100 Subject: [PATCH 22/24] Update api/src/main/java/jakarta/data/event/PreDeleteEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PreDeleteEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PreDeleteEvent.java b/api/src/main/java/jakarta/data/event/PreDeleteEvent.java index 1612436f..5b1db754 100644 --- a/api/src/main/java/jakarta/data/event/PreDeleteEvent.java +++ b/api/src/main/java/jakarta/data/event/PreDeleteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From ab12abe3abe244657fd52abf579b269aa245fc19 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:31:37 +0100 Subject: [PATCH 23/24] Update api/src/main/java/jakarta/data/event/PostUpdateEvent.java Co-authored-by: Nathan Rauh --- api/src/main/java/jakarta/data/event/PostUpdateEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/data/event/PostUpdateEvent.java b/api/src/main/java/jakarta/data/event/PostUpdateEvent.java index 93d70760..2a9e2e27 100644 --- a/api/src/main/java/jakarta/data/event/PostUpdateEvent.java +++ b/api/src/main/java/jakarta/data/event/PostUpdateEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023,2024 Contributors to the Eclipse Foundation + * Copyright (c) 2024 Contributors to the Eclipse Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From fd91006c706162b8d5c54dd661abaedfc4bbc081 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Thu, 21 Nov 2024 12:48:28 +0100 Subject: [PATCH 24/24] add language about transactional and async observers Signed-off-by: Gavin King --- .../jakarta/data/event/LifecycleEvent.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/jakarta/data/event/LifecycleEvent.java b/api/src/main/java/jakarta/data/event/LifecycleEvent.java index 5d3ae1bc..714a0b23 100644 --- a/api/src/main/java/jakarta/data/event/LifecycleEvent.java +++ b/api/src/main/java/jakarta/data/event/LifecycleEvent.java @@ -26,6 +26,25 @@ * ... * } * + *

As usual for a CDI event, an observer of a {@code LifecycleEvent} + * is notified synchronously and immediately by default. An observer may + * elect to receive notifications during a phase of the transaction + * completion cycle by explicitly specifying a {@code TransactionPhase}, + * for example:

+ *
    + *
  • {@code @Observes(during=BEFORE_COMPLETION)} to be notified just + * before transaction completion, or
  • + *
  • {@code @Observes(during=AFTER_SUCCESS)} to be notified after + * successful completion of the transaction.
  • + *
+ *

An observer may choose to be notified asynchronously using + * {@code @ObservesAsync}. However, the mutable state held by the + * {@link #entity} is not in general safe for concurrent access, + * and so portable applications must not use {@code @ObservesAsync} + * to observe a {@code LifecycleEvent}. If the state of an entity is + * accessed from an asynchronous observer method for a lifecycle + * event, the resulting behavior is undefined and unportable.

+ * * * @param the entity type */ @@ -60,9 +79,9 @@ public LifecycleEvent(E entity) { *

* A portable application must not mutate the state of the * entity instance returned by this method. If the state - * of the entity instance is mutated during while event - * listeners are being notified, then the resulting - * behavior is undefined and unportable. + * of the entity instance is mutated while event listeners + * are being notified, the resulting behavior is undefined + * and unportable. */ public E entity() { return entity;