diff --git a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsASTUtils.java b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsASTUtils.java index c7e83cb017..4d5f32dc44 100644 --- a/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsASTUtils.java +++ b/grails-core/src/main/groovy/org/grails/compiler/injection/GrailsASTUtils.java @@ -148,6 +148,8 @@ public final class GrailsASTUtils { @SuppressWarnings("rawtypes") private static final Set ENTITY_ANNOTATIONS = new HashSet<>(); + private static Class JPA_ENTITY_ANNOTATION; + static { ENTITY_ANNOTATIONS.add(grails.persistence.Entity.class); ClassLoader classLoader = GrailsASTUtils.class.getClassLoader(); @@ -160,7 +162,7 @@ public final class GrailsASTUtils { } if (ClassUtils.isPresent("javax.persistence.EntityManagerFactory", classLoader)) { try { - ENTITY_ANNOTATIONS.add(classLoader.loadClass("javax.persistence.Entity")); + JPA_ENTITY_ANNOTATION = classLoader.loadClass("javax.persistence.Entity"); } catch (ClassNotFoundException ignored) { } @@ -858,6 +860,9 @@ public static boolean isConstructorMethod(MethodNode declaredMethod) { @SuppressWarnings("unchecked") public static boolean isDomainClass(ClassNode classNode, SourceUnit sourceNode) { + if (isJpaEntityClass(classNode)) { + return false; + } boolean isDomainClass = GrailsASTUtils.hasAnyAnnotations(classNode, ENTITY_ANNOTATIONS.toArray(new Class[0])); if (!isDomainClass && sourceNode != null) { @@ -884,6 +889,11 @@ public static boolean isDomainClass(ClassNode classNode, SourceUnit sourceNode) return isDomainClass; } + @SuppressWarnings("unchecked") + public static boolean isJpaEntityClass(ClassNode classNode) { + return JPA_ENTITY_ANNOTATION != null && GrailsASTUtils.hasAnnotation(classNode, (Class) JPA_ENTITY_ANNOTATION); + } + public static void addDelegateInstanceMethods(ClassNode classNode, ClassNode delegateNode, Expression delegateInstance) { addDelegateInstanceMethods(classNode, delegateNode, delegateInstance, null); } diff --git a/grails-core/src/main/groovy/org/grails/core/artefact/AnnotationDomainClassArtefactHandler.java b/grails-core/src/main/groovy/org/grails/core/artefact/AnnotationDomainClassArtefactHandler.java index 940d9f5408..3470f72db0 100644 --- a/grails-core/src/main/groovy/org/grails/core/artefact/AnnotationDomainClassArtefactHandler.java +++ b/grails-core/src/main/groovy/org/grails/core/artefact/AnnotationDomainClassArtefactHandler.java @@ -15,10 +15,11 @@ */ package org.grails.core.artefact; +import java.lang.annotation.Annotation; import java.util.HashSet; import java.util.Set; -import javax.persistence.Entity; +import org.springframework.util.ClassUtils; /** * Detects annotated domain classes for EJB3 style mappings. @@ -26,10 +27,24 @@ * @author Graeme Rocher * @since 1.0 */ +@SuppressWarnings("unchecked") public class AnnotationDomainClassArtefactHandler extends DomainClassArtefactHandler { private static final String JPA_MAPPING_STRATEGY = "JPA"; + private static Class JPA_ENTITY_ANNOTATION; + + static { + ClassLoader classLoader = AnnotationDomainClassArtefactHandler.class.getClassLoader(); + if (ClassUtils.isPresent("javax.persistence.EntityManagerFactory", classLoader)) { + try { + JPA_ENTITY_ANNOTATION = (Class) classLoader.loadClass("javax.persistence.Entity"); + } + catch (ClassNotFoundException ignored) { + } + } + } + private final Set jpaClassNames = new HashSet<>(); public Set getJpaClassNames() { @@ -46,7 +61,7 @@ public boolean isArtefactClass(Class clazz) { } public static boolean isJPADomainClass(Class clazz) { - return clazz != null && clazz.getAnnotation(Entity.class) != null; + return clazz != null && JPA_ENTITY_ANNOTATION != null && clazz.getAnnotation(JPA_ENTITY_ANNOTATION) != null; } } diff --git a/grails-core/src/main/groovy/org/grails/core/artefact/DomainClassArtefactHandler.java b/grails-core/src/main/groovy/org/grails/core/artefact/DomainClassArtefactHandler.java index fb0182dfc6..cac0a28109 100644 --- a/grails-core/src/main/groovy/org/grails/core/artefact/DomainClassArtefactHandler.java +++ b/grails-core/src/main/groovy/org/grails/core/artefact/DomainClassArtefactHandler.java @@ -54,8 +54,6 @@ public class DomainClassArtefactHandler extends ArtefactHandlerAdapter implement private static final String GRAILS_PACKAGE_PREFIX = "grails."; - private static final String JAVAX_PERSISTENCE = "javax.persistence"; - public DomainClassArtefactHandler() { super(TYPE, GrailsDomainClass.class, DefaultGrailsDomainClass.class, null, true); } @@ -99,7 +97,8 @@ public boolean isArtefact(ClassNode classNode) { URL url = GrailsASTUtils.getSourceUrl(classNode); if (url != null) { - return GrailsResourceUtils.isDomainClass(url); + boolean isDomainClass = GrailsResourceUtils.isDomainClass(url); + return isDomainClass && !GrailsASTUtils.isJpaEntityClass(classNode); } else { return super.isArtefact(classNode); @@ -158,7 +157,7 @@ private static boolean doIsDomainClassCheck(Class clazz) { String annName = annType.getSimpleName(); String pkgName = annType.getPackage().getName(); - if (ENTITY_ANN_NAME.equals(annName) && pkgName.startsWith(GRAILS_PACKAGE_PREFIX) || pkgName.startsWith(JAVAX_PERSISTENCE)) { + if (ENTITY_ANN_NAME.equals(annName) && pkgName.startsWith(GRAILS_PACKAGE_PREFIX)) { return true; } } diff --git a/grails-core/src/test/groovy/org/grails/compiler/injection/GrailsASTUtilsSpec.groovy b/grails-core/src/test/groovy/org/grails/compiler/injection/GrailsASTUtilsSpec.groovy index 325d291d98..abd8dad1e2 100644 --- a/grails-core/src/test/groovy/org/grails/compiler/injection/GrailsASTUtilsSpec.groovy +++ b/grails-core/src/test/groovy/org/grails/compiler/injection/GrailsASTUtilsSpec.groovy @@ -136,7 +136,8 @@ class GrailsASTUtilsSpec extends Specification { someEntitySourceUnit.getName() >> someEntityFile.absolutePath expect: 'SomeJpaEntity should be recognized as a domain because annotated with @grails.persistence.Entity' - GrailsASTUtils.isDomainClass(new ClassNode(SomeJpaEntity), someEntitySourceUnit) + GrailsASTUtils.isJpaEntityClass(new ClassNode(SomeJpaEntity)) + !GrailsASTUtils.isDomainClass(new ClassNode(SomeJpaEntity), someEntitySourceUnit) } void 'test domain class annotated with @grails.gorm.annotation.Entity'() {