From a291ad434042d13f810f31b961fc42cff8a2ad80 Mon Sep 17 00:00:00 2001 From: Nathan Rauh <nathan.rauh@us.ibm.com> Date: Tue, 27 Feb 2024 10:15:12 -0600 Subject: [PATCH 1/3] Fix TCK per spec requirement to disallow Delete with boolean return type Signed-off-by: Nathan Rauh <nathan.rauh@us.ibm.com> --- .../data/standalone/persistence/Catalog.java | 5 +++ .../persistence/PersistenceEntityTests.java | 31 ++++++++++++++++--- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/Catalog.java b/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/Catalog.java index 8500a754c..71c3cb38b 100644 --- a/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/Catalog.java +++ b/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/Catalog.java @@ -18,12 +18,14 @@ import java.util.Collection; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.stream.Stream; import jakarta.data.Order; import jakarta.data.Streamable; import jakarta.data.repository.DataRepository; import jakarta.data.repository.Delete; +import jakarta.data.repository.Find; import jakarta.data.repository.Insert; import jakarta.data.repository.OrderBy; import jakarta.data.repository.Param; @@ -44,6 +46,9 @@ public interface Catalog extends DataRepository<Product, String> { @Insert Product[] addMultiple(Product... products); + @Find + Optional<Product> get(String productNum); + @Update Product modify(Product product); diff --git a/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/PersistenceEntityTests.java b/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/PersistenceEntityTests.java index 325e1f20e..d02c2b401 100644 --- a/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/PersistenceEntityTests.java +++ b/tck/src/main/java/ee/jakarta/tck/data/standalone/persistence/PersistenceEntityTests.java @@ -24,6 +24,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -150,7 +151,14 @@ public void testInsertEntityThatAlreadyExists() { // expected } - assertEquals(true, catalog.remove(prod1)); + Optional<Product> result; + result = catalog.get("TEST-PROD-94"); + assertEquals(true, result.isPresent()); + + catalog.remove(prod1); + + result = catalog.get("TEST-PROD-94"); + assertEquals(false, result.isPresent()); } @Assertion(id = "133", strategy = "Use a repository method with the Like keyword.") @@ -352,9 +360,24 @@ public void testVersionedInsertUpdateDelete() { prod2.setPrice(1.34); assertEquals(null, catalog.modify(prod2)); - assertEquals(true, catalog.remove(prod1)); - assertEquals(false, catalog.remove(prod1)); // already removed - assertEquals(false, catalog.remove(prod2)); // still at old version + catalog.remove(prod1); + + Optional<Product> found = catalog.get("TEST-PROD-91"); + assertEquals(false, found.isPresent()); + + try { + catalog.remove(prod1); // already removed + fail("Must raise OptimisticLockingFailureException for entity that was already removed from the database."); + } catch (OptimisticLockingFailureException x) { + // expected + } + + try { + catalog.remove(prod2); // still at old version + fail("Must raise OptimisticLockingFailureException for entity with non-matching version."); + } catch (OptimisticLockingFailureException x) { + // expected + } assertEquals(1L, catalog.deleteByProductNumLike("TEST-PROD-%")); } From bf8fea5f8c290ee87fbc35478e7697e54d90a326 Mon Sep 17 00:00:00 2001 From: Nathan Rauh <nathan.rauh@us.ibm.com> Date: Tue, 27 Feb 2024 10:15:37 -0600 Subject: [PATCH 2/3] Fix JavaDoc errors --- api/src/main/java/jakarta/data/repository/Delete.java | 2 +- api/src/main/java/jakarta/data/repository/Insert.java | 2 +- api/src/main/java/jakarta/data/repository/Save.java | 2 +- api/src/main/java/jakarta/data/repository/Update.java | 3 +-- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/jakarta/data/repository/Delete.java b/api/src/main/java/jakarta/data/repository/Delete.java index ee5e015ea..dfe0c28e3 100644 --- a/api/src/main/java/jakarta/data/repository/Delete.java +++ b/api/src/main/java/jakarta/data/repository/Delete.java @@ -64,7 +64,7 @@ * <p>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. - * </p + * </p> */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/api/src/main/java/jakarta/data/repository/Insert.java b/api/src/main/java/jakarta/data/repository/Insert.java index 7fef9eccd..2e01fabfa 100644 --- a/api/src/main/java/jakarta/data/repository/Insert.java +++ b/api/src/main/java/jakarta/data/repository/Insert.java @@ -69,7 +69,7 @@ * <p>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. - * </p + * </p> */ @Documented @Retention(RetentionPolicy.RUNTIME) diff --git a/api/src/main/java/jakarta/data/repository/Save.java b/api/src/main/java/jakarta/data/repository/Save.java index d227665d8..f5216aebc 100644 --- a/api/src/main/java/jakarta/data/repository/Save.java +++ b/api/src/main/java/jakarta/data/repository/Save.java @@ -64,7 +64,7 @@ * <p>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. - * </p + * </p> * * @see Insert * @see Update diff --git a/api/src/main/java/jakarta/data/repository/Update.java b/api/src/main/java/jakarta/data/repository/Update.java index cf05d7f1a..7269dc1ab 100644 --- a/api/src/main/java/jakarta/data/repository/Update.java +++ b/api/src/main/java/jakarta/data/repository/Update.java @@ -44,7 +44,6 @@ * Application of the {@code Update} annotation to a method with any other signature is not portable between Jakarta * Data providers. * </p> - * </p> * <p>For example, consider an interface representing a garage:</p> * <pre> * {@code @Repository} @@ -73,7 +72,7 @@ * <p>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. - * </p + * </p> */ @Documented @Retention(RetentionPolicy.RUNTIME) From 7ff4aa68d1e640dc51a6bfd16644ea2f0bcaac95 Mon Sep 17 00:00:00 2001 From: Nathan Rauh <nathan.rauh@us.ibm.com> Date: Tue, 27 Feb 2024 10:40:41 -0600 Subject: [PATCH 3/3] Disallow other usage so as to reserve it for future spec versions --- api/src/main/java/jakarta/data/repository/Delete.java | 6 +++--- api/src/main/java/jakarta/data/repository/Update.java | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/jakarta/data/repository/Delete.java b/api/src/main/java/jakarta/data/repository/Delete.java index dfe0c28e3..214e06940 100644 --- a/api/src/main/java/jakarta/data/repository/Delete.java +++ b/api/src/main/java/jakarta/data/repository/Delete.java @@ -28,8 +28,9 @@ * <p>Lifecycle annotation for repository methods which perform delete operations.</p> * * <p>The {@code Delete} annotation indicates that the annotated repository method deletes the state of one or more - * entities from the database. + * entities from the database. The method must follow one of the following patterns. * </p> + * <h2>Parameter for Entity Instances</h2> * <p>A {@code Delete} method might accept an instance or instances of an entity class. In this case, the method must * have exactly one parameter whose type is either: * </p> @@ -40,8 +41,6 @@ * <p>The annotated method must be declared {@code void}. * </p> * <p>All Jakarta Data providers are required to accept a {@code Delete} method which conforms to this signature. - * Application of the {@code Delete} annotation to a method with any other signature is not portable between Jakarta - * Data providers, excepting the specific case of a repository method with no parameters, as described below. * </p> * <p>For example, consider an interface representing a garage:</p> * <pre> @@ -57,6 +56,7 @@ * if the entity with a matching identifier does not have a matching version, the annotated method must raise * {@link jakarta.data.exceptions.OptimisticLockingFailureException}. * </p> + * <h2>Without Parameters</h2> * <p>Alternatively, the {@code Delete} annotation may be applied to a repository method with no parameters, indicating * that the annotated method deletes all instances of the primary entity type. In this case, the annotated method must * either be declared {@code void}, or return {@code int} or {@code long}. diff --git a/api/src/main/java/jakarta/data/repository/Update.java b/api/src/main/java/jakarta/data/repository/Update.java index 7269dc1ab..ceb86bd22 100644 --- a/api/src/main/java/jakarta/data/repository/Update.java +++ b/api/src/main/java/jakarta/data/repository/Update.java @@ -30,7 +30,7 @@ * <p>The {@code Update} annotation indicates that the annotated repository method updates the state of one or more * entities already held in the database. * </p> - * <p>An {@code Update} method might accept an instance or instances of an entity class. In this case, the method must + * <p>An {@code Update} method accepts an instance or instances of an entity class. The method must * have exactly one parameter whose type is either: * </p> * <ul> @@ -41,8 +41,6 @@ * its parameter. * <p> * All Jakarta Data providers are required to accept an {@code Update} method which conforms to this signature. - * Application of the {@code Update} annotation to a method with any other signature is not portable between Jakarta - * Data providers. * </p> * <p>For example, consider an interface representing a garage:</p> * <pre>