From 8db57d791b5e4a2a8189e914fc2900fe32760815 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 31 Mar 2024 14:38:04 +0200 Subject: [PATCH] when CDI is missing, do still add an @Inject annotation on the constructor at least when jakarta.inject is available Signed-off-by: Gavin King --- .../annotation/AnnotationMetaEntity.java | 19 +++++++++++++++-- .../annotation/RepositoryConstructor.java | 21 ++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java index 89e2055675..d74cdaa34c 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/AnnotationMetaEntity.java @@ -535,13 +535,28 @@ public class AnnotationMetaEntity extends AnnotationMeta { sessionType = HIB_STATELESS_SESSION; addDaoConstructor( null ); } - if ( jakartaDataRepository && !quarkusInjection - && context.addDependentAnnotation() ) { + if ( needsDefaultConstructor() ) { addDefaultConstructor(); } } } + /** + * For usage with CDI, but outside Quarkus, Jakarta Data + * repositories use {@code @PersistenceUnit} to obtain an + * {@code EntityManagerFactory} via field injection. So in + * that case we will need a {@link DefaultConstructor default + * constructor}. We don't do this in Quarkus, because there + * we can just inject the {@code StatelessSession} directly, + * and so in Quarkus we don't need the default constructor + * at all. + */ + boolean needsDefaultConstructor() { + return jakartaDataRepository + && !quarkusInjection + && context.addDependentAnnotation(); + } + private @Nullable ExecutableElement findSessionGetter(TypeElement type) { if ( !hasAnnotation( type, ENTITY, MAPPED_SUPERCLASS, EMBEDDABLE ) || isPanacheType( type ) ) { diff --git a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/RepositoryConstructor.java b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/RepositoryConstructor.java index 5523047706..cf285b697d 100644 --- a/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/RepositoryConstructor.java +++ b/tooling/metamodel-generator/src/main/java/org/hibernate/processor/annotation/RepositoryConstructor.java @@ -17,7 +17,7 @@ import org.hibernate.processor.util.Constants; * @author Gavin King */ public class RepositoryConstructor implements MetaAttribute { - private final Metamodel annotationMetaEntity; + private final AnnotationMetaEntity annotationMetaEntity; private final String constructorName; private final String methodName; private final String sessionTypeName; @@ -30,7 +30,7 @@ public class RepositoryConstructor implements MetaAttribute { private final boolean quarkusInjection; public RepositoryConstructor( - Metamodel annotationMetaEntity, + AnnotationMetaEntity annotationMetaEntity, String constructorName, String methodName, String sessionTypeName, @@ -135,6 +135,11 @@ public class RepositoryConstructor implements MetaAttribute { return declaration.toString(); } + /** + * In Quarkus we use the Quarkus-specific {@code @PersistenceUnit} + * CDI qualifier annotation to inject the {@code StatelessSession} + * directly. + */ private void qualifier(StringBuilder declaration) { if ( addInjectAnnotation && quarkusInjection && dataStore != null ) { declaration @@ -146,13 +151,23 @@ public class RepositoryConstructor implements MetaAttribute { } } + /** + * In Quarkus we inject the {@code StatelessSession} + * directly via the constructor. But this doesn't work + * in other CDI implementations, where we need to use + * the JPA {@code @PersistenceUnit} annotation for + * field injection of an {@code EntityManager}. In + * that case, CDI will instantiate the repository via + * a {@link DefaultConstructor default constructor}, + * so we don't need to mark this one {@code @Inject}. + */ private void inject(StringBuilder declaration) { // Jakarta Data repositories are instantiated // via the default constructor, so in that // case, this one is just for testing, unless // we are in Quarkus where we can use // constructor injection - if ( addInjectAnnotation && (!dataRepository || quarkusInjection) ) { + if ( addInjectAnnotation && !annotationMetaEntity.needsDefaultConstructor() ) { declaration .append('@') .append(annotationMetaEntity.importType("jakarta.inject.Inject"))