glassfish
  1. glassfish
  2. GLASSFISH-17412

Annotations in plain java classes shouldn't be processed

    Details

    • Type: Bug Bug
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: 3.1.1_b12
    • Fix Version/s: future release
    • Component/s: deployment
    • Labels:
      None

      Description

      When deploying an EJB-module, Glassfish seems to scan for injection annotations in all classes, not just the ones marked as EJB.

      This can lead to problems when plain java classes (no @Stateless, @Stateful, etc) contain annotations that would be invalid for container-managed classes, because Glassfish then refuses to deploy the application. It shouldn't do this, and instead ignore these annotations on unmanaged classes.

      I've attached an example project that demonstrates this problem. It contains a non-EJB class AbstractTestA that contains an unresolvable @EJB annotation on a field, which causes deployment to fail:

      SEVERE: Cannot resolve reference Local ejb-ref name=test.AbstractTestA/test,Local 3.x interface =test.TestA,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session
      SEVERE: Exception while deploying the app [ejb-reference-testcase]
      SEVERE: Cannot resolve reference Local ejb-ref name=test.AbstractTestA/test,Local 3.x interface =test.TestA,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session
      java.lang.RuntimeException: Cannot resolve reference Local ejb-ref name=test.AbstractTestA/test,Local 3.x interface =test.TestA,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session
      at com.sun.enterprise.deployment.util.EjbBundleValidator.accept(EjbBundleValidator.java:608)
      at com.sun.enterprise.deployment.EjbBundleDescriptor.visit(EjbBundleDescriptor.java:760)
      at com.sun.enterprise.deployment.Application.visit(Application.java:1765)
      at com.sun.enterprise.deployment.archivist.ApplicationFactory.openArchive(ApplicationFactory.java:195)
      at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:181)
      at org.glassfish.javaee.core.deployment.DolProvider.load(DolProvider.java:93)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.loadDeployer(ApplicationLifecycle.java:828)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.setupContainerInfos(ApplicationLifecycle.java:770)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:368)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:240)
      at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:382)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$1.execute(CommandRunnerImpl.java:355)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:370)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1064)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl.access$1200(CommandRunnerImpl.java:96)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1244)
      at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1232)
      at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:459)
      at com.sun.enterprise.v3.admin.AdminAdapter.service(AdminAdapter.java:209)
      at com.sun.grizzly.tcp.http11.GrizzlyAdapter.service(GrizzlyAdapter.java:168)
      at com.sun.enterprise.v3.server.HK2Dispatcher.dispath(HK2Dispatcher.java:117)
      at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:238)
      at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828)
      at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725)
      at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019)
      at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225)
      at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137)
      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104)
      at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90)
      at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79)
      at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54)
      at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59)
      at com.sun.grizzly.ContextTask.run(ContextTask.java:71)
      at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532)
      at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513)
      at java.lang.Thread.run(Thread.java:680)

      SEVERE: Exception while deploying the app [ejb-reference-testcase] : Cannot resolve reference Local ejb-ref name=test.AbstractTestA/test,Local 3.x interface =test.TestA,ejb-link=null,lookup=,mappedName=,jndi-name=,refType=Session

      My actual use case is only slightly more complex: I'm using a shared library jar in several EJB-modules, that contains both EJB interfaces and abstract implementations. The abstract implementations include an @EJB reference to their own interface, to be able to start certain operations in a new transaction.

      Each EJB-module implements some (often not all) of the interfaces, using the provided abstract implementation. Because only the actual implementations are marked with @Stateless (etc) and the abstract ones are not, injection annotation processing should only happen for the beans that are actually implemented. This worked properly in Glassfish 2.1.

        Activity

        Hide
        Hong Zhang added a comment -

        Scrub bugs for 4.0 HCF. Did not get a chance to look into this one, as the changes for this one will be very involving, re-target for later release.

        Show
        Hong Zhang added a comment - Scrub bugs for 4.0 HCF. Did not get a chance to look into this one, as the changes for this one will be very involving, re-target for later release.
        Hide
        Hong Zhang added a comment -

        Will look at this for trunk (the changes for this will be too involving for 3.1.*).

        Show
        Hong Zhang added a comment - Will look at this for trunk (the changes for this will be too involving for 3.1.*).
        Hide
        Hong Zhang added a comment -

        Yes today we scan all the classes for annotations as it's hard to determine which we should scan and should not ahead of the time. But it might be possible to filter the processed results to remove the unwanted processing.
        The reason it used to work in 2.* is we did not scan libraries for annotation processing which was a bug and we fixed that in 3.*.

        Show
        Hong Zhang added a comment - Yes today we scan all the classes for annotations as it's hard to determine which we should scan and should not ahead of the time. But it might be possible to filter the processed results to remove the unwanted processing. The reason it used to work in 2.* is we did not scan libraries for annotation processing which was a bug and we fixed that in 3.*.
        Hide
        Cheng Fang added a comment -

        Assign to deployment. Hong, can you take a look?

        Show
        Cheng Fang added a comment - Assign to deployment. Hong, can you take a look?
        Hide
        Sanjeeb Sahoo added a comment -

        Seems like a bug to me. @EJB should only be processed for classes that are "injection capable."

        Show
        Sanjeeb Sahoo added a comment - Seems like a bug to me. @EJB should only be processed for classes that are "injection capable."
        Hide
        omolenkamp added a comment -

        "@EJB and other annotations on the super classes of EJB bean class are part of the dependency of this EJB, and need to be processed. "

        Yes, but what's happening is that these annotations are also processed on classes that aren't EJB's themselves, and don't have any subclasses that are EJB's either. There's no reason to do this, and it will break the setup I described.

        Show
        omolenkamp added a comment - "@EJB and other annotations on the super classes of EJB bean class are part of the dependency of this EJB, and need to be processed. " Yes, but what's happening is that these annotations are also processed on classes that aren't EJB's themselves, and don't have any subclasses that are EJB's either. There's no reason to do this, and it will break the setup I described.
        Hide
        Cheng Fang added a comment -

        @EJB and other annotations on the super classes of EJB bean class are part of the dependency of this EJB, and need to be processed. This is required by Java EE and EJB spec.

        If some ejb-ref only apply to certain concrete EJB bean class, then the concrete bean class is better place than the common super class. You may want to use lookup, or have a non-annotated setter method in super class, to be overridden with a setter method annotated with @EJB in subclass if needed.

        Show
        Cheng Fang added a comment - @EJB and other annotations on the super classes of EJB bean class are part of the dependency of this EJB, and need to be processed. This is required by Java EE and EJB spec. If some ejb-ref only apply to certain concrete EJB bean class, then the concrete bean class is better place than the common super class. You may want to use lookup, or have a non-annotated setter method in super class, to be overridden with a setter method annotated with @EJB in subclass if needed.

          People

          • Assignee:
            Hong Zhang
            Reporter:
            omolenkamp
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated: