Permalink
Comparing changes
Open a pull request
- 2 commits
- 10 files changed
- 0 commit comments
- 2 contributors
Commits on Apr 15, 2019
… interfaces that do not have concrete subclasses
Commits on Apr 24, 2019
WFLY-11870 Do not process resource annotations on abstract classes or …
Unified
Split
Showing
with
224 additions
and 1 deletion.
- +35 −1 ee/src/main/java/org/jboss/as/ee/component/deployers/ModuleJndiBindingProcessor.java
- +13 −0 ...rc/test/java/org/jboss/as/test/integration/ejb/annotationprocessing/AbstractReferencingBeanA.java
- +11 −0 ...on/basic/src/test/java/org/jboss/as/test/integration/ejb/annotationprocessing/ReferencedBean.java
- +5 −0 ...src/test/java/org/jboss/as/test/integration/ejb/annotationprocessing/ReferencedBeanInterface.java
- +10 −0 ...c/test/java/org/jboss/as/test/integration/ejb/annotationprocessing/ReferencingBeanBInterface.java
- +4 −0 ...basic/src/test/java/org/jboss/as/test/integration/ejb/annotationprocessing/ReferencingClassA.java
- +4 −0 ...basic/src/test/java/org/jboss/as/test/integration/ejb/annotationprocessing/ReferencingClassB.java
- +7 −0 ...c/src/test/java/org/jboss/as/test/integration/ejb/annotationprocessing/ReferencingComponentA.java
- +7 −0 ...c/src/test/java/org/jboss/as/test/integration/ejb/annotationprocessing/ReferencingComponentB.java
- +128 −0 ...org/jboss/as/test/integration/ejb/annotationprocessing/ResourceAnnotationsProcessingTestCase.java
| @@ -47,6 +47,9 @@ | ||
| import org.jboss.as.server.deployment.DeploymentUnit; | ||
| import org.jboss.as.server.deployment.DeploymentUnitProcessingException; | ||
| import org.jboss.as.server.deployment.DeploymentUnitProcessor; | ||
| import org.jboss.as.server.deployment.annotation.CompositeIndex; | ||
| import org.jboss.jandex.ClassInfo; | ||
| import org.jboss.jandex.DotName; | ||
| import org.jboss.modules.Module; | ||
| import org.jboss.msc.service.CircularDependencyException; | ||
| import org.jboss.msc.service.DuplicateServiceException; | ||
| @@ -61,6 +64,7 @@ | ||
| import org.jboss.msc.service.StartException; | ||
| import org.jboss.msc.service.StopContext; | ||
|
|
||
| import java.lang.reflect.Modifier; | ||
| import java.util.HashMap; | ||
| import java.util.HashSet; | ||
| import java.util.List; | ||
| @@ -158,8 +162,9 @@ public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentU | ||
| //were only intended to be installed when running as an app client | ||
| boolean appClient = DeploymentTypeMarker.isType(DeploymentType.APPLICATION_CLIENT, deploymentUnit) || this.appclient; | ||
|
|
||
|
|
||
| if (!MetadataCompleteMarker.isMetadataComplete(phaseContext.getDeploymentUnit()) && !appClient) { | ||
| final CompositeIndex index = deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.COMPOSITE_ANNOTATION_INDEX); | ||
|
|
||
| for (EEModuleClassDescription config : eeModuleDescription.getClassDescriptions()) { | ||
| if (handledClasses.contains(config.getClassName())) { | ||
| continue; | ||
| @@ -168,6 +173,16 @@ public void deploy(final DeploymentPhaseContext phaseContext) throws DeploymentU | ||
| continue; | ||
| } | ||
| final Set<BindingConfiguration> classLevelBindings = new HashSet<>(config.getBindingConfigurations()); | ||
| // only process concrete classes and their superclasses | ||
| // (An Index contains info on all classes in a jar, and the CompositeIndex in the 'index' var aggregates | ||
| // all the Index objects for the jars visible to the deployment unit. So it can be scanned for relationships | ||
| // between classes and not miss out on any.) | ||
| if (!classLevelBindings.isEmpty()) { | ||
| ClassInfo classInfo = index.getClassByName(DotName.createSimple(config.getClassName())); | ||
| if (!isConcreteClass(classInfo) && !hasConcreteSubclass(index, classInfo)) { | ||
| continue; | ||
| } | ||
| } | ||
| for (BindingConfiguration binding : classLevelBindings) { | ||
| final String bindingName = binding.getName(); | ||
| final boolean compBinding = bindingName.startsWith("java:comp") || !bindingName.startsWith("java:"); | ||
| @@ -304,6 +319,25 @@ public static boolean equals(Object one, Object two) { | ||
| return one == two || (one != null && one.equals(two)); | ||
| } | ||
|
|
||
| private static boolean isConcreteClass(ClassInfo classInfo) { | ||
| return !Modifier.isAbstract(classInfo.flags()) && !Modifier.isInterface(classInfo.flags()); | ||
| } | ||
|
|
||
| private static boolean hasConcreteSubclass(CompositeIndex index, ClassInfo classInfo) { | ||
| final Set<ClassInfo> subclasses; | ||
| if (Modifier.isInterface(classInfo.flags())) { | ||
| subclasses = index.getAllKnownImplementors(classInfo.name()); | ||
| } else { | ||
| subclasses = index.getAllKnownSubclasses(classInfo.name()); | ||
| } | ||
| for (ClassInfo subclass: subclasses) { | ||
| if (isConcreteClass(subclass)) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| public void undeploy(DeploymentUnit context) { | ||
| } | ||
|
|
||
| @@ -0,0 +1,13 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| import javax.ejb.EJB; | ||
|
|
||
| public abstract class AbstractReferencingBeanA { | ||
|
|
||
| @EJB | ||
| private ReferencedBeanInterface referencedBean; | ||
|
|
||
| public String relayHello() { | ||
| return referencedBean.sayHello(); | ||
| } | ||
| } |
| @@ -0,0 +1,11 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| import javax.ejb.Stateless; | ||
|
|
||
| @Stateless | ||
| public class ReferencedBean implements ReferencedBeanInterface { | ||
| @Override | ||
| public String sayHello() { | ||
| return "Hello!"; | ||
| } | ||
| } |
| @@ -0,0 +1,5 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| public interface ReferencedBeanInterface { | ||
| String sayHello(); | ||
| } |
| @@ -0,0 +1,10 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| import javax.ejb.EJB; | ||
|
|
||
| public interface ReferencingBeanBInterface { | ||
|
|
||
| @EJB | ||
| ReferencedBeanInterface refencedBean = null; | ||
|
|
||
| } |
| @@ -0,0 +1,4 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| public class ReferencingClassA extends AbstractReferencingBeanA { | ||
| } |
| @@ -0,0 +1,4 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| public class ReferencingClassB implements ReferencingBeanBInterface { | ||
| } |
| @@ -0,0 +1,7 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| import javax.ejb.Stateless; | ||
|
|
||
| @Stateless | ||
| public class ReferencingComponentA extends AbstractReferencingBeanA { | ||
| } |
| @@ -0,0 +1,7 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| import javax.ejb.Stateless; | ||
|
|
||
| @Stateless | ||
| public class ReferencingComponentB implements ReferencingBeanBInterface { | ||
| } |
| @@ -0,0 +1,128 @@ | ||
| package org.jboss.as.test.integration.ejb.annotationprocessing; | ||
|
|
||
| import org.jboss.arquillian.container.spi.client.container.DeploymentException; | ||
| import org.jboss.arquillian.container.test.api.Deployer; | ||
| import org.jboss.arquillian.container.test.api.Deployment; | ||
| import org.jboss.arquillian.junit.Arquillian; | ||
| import org.jboss.arquillian.test.api.ArquillianResource; | ||
| import org.jboss.shrinkwrap.api.ShrinkWrap; | ||
| import org.jboss.shrinkwrap.api.spec.WebArchive; | ||
| import org.junit.Test; | ||
| import org.junit.runner.RunWith; | ||
|
|
||
| @RunWith(Arquillian.class) | ||
| public class ResourceAnnotationsProcessingTestCase { | ||
|
|
||
| private static final String ABSTRACT_REFERENCING_INTERFACE_WITHOUT_IMPL = "abstract-referencing-interface-without-impl"; | ||
| private static final String INTERFACE_REFERENCING_INTERFACE_WITHOUT_IMPL = "interface-referencing-interface-without-impl"; | ||
| private static final String EJBS_REFERENCING_INTERFACE_WITH_IMPL = "ejbs-referencing-interface-with-impl"; | ||
| private static final String EJBS_REFERENCING_INTERFACE_WITHOUT_IMPL = "ejbs-referencing-interface-without-impl"; | ||
| private static final String CLASSES_REFERENCING_INTERFACE_WITH_IMPL = "classes-referencing-interface-with-impl"; | ||
| private static final String CLASSES_REFERENCING_INTERFACE_WITHOUT_IMPL = "classes-referencing-interface-without-impl"; | ||
|
|
||
| @ArquillianResource | ||
| private Deployer deployer; | ||
|
|
||
| @Deployment(name = ABSTRACT_REFERENCING_INTERFACE_WITHOUT_IMPL, managed = false) | ||
| public static WebArchive createDeployment1() { | ||
| final WebArchive war = ShrinkWrap.create(WebArchive.class, | ||
| ABSTRACT_REFERENCING_INTERFACE_WITHOUT_IMPL + ".war"); | ||
| war.addClass(ReferencedBeanInterface.class); | ||
| war.addClass(AbstractReferencingBeanA.class); | ||
| return war; | ||
| } | ||
|
|
||
| @Deployment(name = INTERFACE_REFERENCING_INTERFACE_WITHOUT_IMPL, managed = false) | ||
| public static WebArchive createDeployment2() { | ||
| final WebArchive war = ShrinkWrap.create(WebArchive.class, | ||
| INTERFACE_REFERENCING_INTERFACE_WITHOUT_IMPL + ".war"); | ||
| war.addClass(ReferencedBeanInterface.class); | ||
| war.addClass(ReferencingBeanBInterface.class); | ||
| return war; | ||
| } | ||
|
|
||
| @Deployment(name = EJBS_REFERENCING_INTERFACE_WITH_IMPL, managed = false) | ||
| public static WebArchive createDeployment3() { | ||
| final WebArchive war = ShrinkWrap.create(WebArchive.class, | ||
| EJBS_REFERENCING_INTERFACE_WITH_IMPL + ".war"); | ||
| war.addClass(ReferencedBeanInterface.class); | ||
| war.addClass(ReferencedBean.class); | ||
| war.addClass(AbstractReferencingBeanA.class); | ||
| war.addClass(ReferencingComponentA.class); | ||
| war.addClass(ReferencingBeanBInterface.class); | ||
| war.addClass(ReferencingComponentB.class); | ||
| return war; | ||
| } | ||
|
|
||
| @Deployment(name = EJBS_REFERENCING_INTERFACE_WITHOUT_IMPL, managed = false) | ||
| public static WebArchive createDeployment4() { | ||
| final WebArchive war = ShrinkWrap.create(WebArchive.class, | ||
| EJBS_REFERENCING_INTERFACE_WITHOUT_IMPL + ".war"); | ||
| war.addClass(ReferencedBeanInterface.class); | ||
| war.addClass(AbstractReferencingBeanA.class); | ||
| war.addClass(ReferencingComponentA.class); | ||
| war.addClass(ReferencingBeanBInterface.class); | ||
| war.addClass(ReferencingComponentB.class); | ||
| return war; | ||
| } | ||
|
|
||
| @Deployment(name = CLASSES_REFERENCING_INTERFACE_WITH_IMPL, managed = false) | ||
| public static WebArchive createDeployment5() { | ||
| final WebArchive war = ShrinkWrap.create(WebArchive.class, | ||
| CLASSES_REFERENCING_INTERFACE_WITH_IMPL + ".war"); | ||
| war.addClass(ReferencedBeanInterface.class); | ||
| war.addClass(ReferencedBean.class); | ||
| war.addClass(AbstractReferencingBeanA.class); | ||
| war.addClass(ReferencingClassA.class); | ||
| war.addClass(ReferencingBeanBInterface.class); | ||
| war.addClass(ReferencingClassB.class); | ||
| return war; | ||
| } | ||
|
|
||
| @Deployment(name = CLASSES_REFERENCING_INTERFACE_WITHOUT_IMPL, managed = false) | ||
| public static WebArchive createDeployment6() { | ||
| final WebArchive war = ShrinkWrap.create(WebArchive.class, | ||
| CLASSES_REFERENCING_INTERFACE_WITHOUT_IMPL + ".war"); | ||
| war.addClass(ReferencedBeanInterface.class); | ||
| war.addClass(AbstractReferencingBeanA.class); | ||
| war.addClass(ReferencingClassA.class); | ||
| war.addClass(ReferencingBeanBInterface.class); | ||
| war.addClass(ReferencingClassB.class); | ||
| return war; | ||
| } | ||
|
|
||
| @Test | ||
| public void testAbstractReferencingInterfaceWithoutImpl() { | ||
| tryDeployment(ABSTRACT_REFERENCING_INTERFACE_WITHOUT_IMPL); | ||
| } | ||
|
|
||
| @Test | ||
| public void testInterfaceReferencingInterfaceWithoutImpl() { | ||
| tryDeployment(INTERFACE_REFERENCING_INTERFACE_WITHOUT_IMPL); | ||
| } | ||
|
|
||
| @Test | ||
| public void testEjbsReferencingInterfaceWithImpl() { | ||
| tryDeployment(EJBS_REFERENCING_INTERFACE_WITH_IMPL); | ||
| } | ||
|
|
||
| @Test(expected = DeploymentException.class) | ||
| public void testEjbsReferencingInterfaceWithoutImpl() { | ||
| tryDeployment(EJBS_REFERENCING_INTERFACE_WITHOUT_IMPL); | ||
| } | ||
|
|
||
| @Test | ||
| public void testClassesReferencingInterfaceWithImpl() { | ||
| tryDeployment(CLASSES_REFERENCING_INTERFACE_WITH_IMPL); | ||
| } | ||
|
|
||
| @Test(expected = DeploymentException.class) | ||
| public void testClassesReferencingInterfaceWithoutImpl() { | ||
| tryDeployment(CLASSES_REFERENCING_INTERFACE_WITHOUT_IMPL); | ||
| } | ||
|
|
||
| private void tryDeployment(String name) { | ||
| deployer.deploy(name); | ||
| deployer.undeploy(name); | ||
| } | ||
| } |