glassfish
  1. glassfish
  2. GLASSFISH-18152

java.lang.ClassNotFoundException when deploying CDI-enabled EAR application

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 3.1.1
    • Fix Version/s: 3.1.2, 4.0
    • Component/s: cdi
    • Labels:
      None

      Description

      I've got following exception while deploying attached application:

      org.jboss.weld.exceptions.WeldException: by java.lang.NoClassDefFoundError: test/war1/Ejb
      at org.jboss.weld.bean.proxy.ProxyFactory.getProxyClass(ProxyFactory.java:259)
      at org.jboss.weld.bean.AbstractClassBean.createEnhancedSubclass(AbstractClassBean.java:673)
      at org.jboss.weld.bean.AbstractClassBean.initEnhancedSubclass(AbstractClassBean.java:659)
      at org.jboss.weld.bean.AbstractClassBean.initializeAfterBeanDiscovery(AbstractClassBean.java:354)
      at org.jboss.weld.bootstrap.BeanDeployment.doAfterBeanDiscovery(BeanDeployment.java:232)
      at org.jboss.weld.bootstrap.BeanDeployment.afterBeanDiscovery(BeanDeployment.java:221)
      at org.jboss.weld.bootstrap.WeldBootstrap.deployBeans(WeldBootstrap.java:375)
      at org.glassfish.weld.WeldDeployer.event(WeldDeployer.java:170)
      at org.glassfish.kernel.event.EventsImpl.send(EventsImpl.java:128)
      at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:270)
      at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:461)
      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 org.glassfish.admin.rest.ResourceUtil.runCommand(ResourceUtil.java:202)
      at org.glassfish.admin.rest.ResourceUtil.runCommand(ResourceUtil.java:195)
      at org.glassfish.admin.rest.resources.TemplateListOfResource.createResource(TemplateListOfResource.java:148)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at com.sun.jersey.spi.container.JavaMethodInvokerFactory$1.invoke(JavaMethodInvokerFactory.java:60)
      at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:205)
      at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:75)
      at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:288)
      at com.sun.jersey.server.impl.uri.rules.SubLocatorRule.accept(SubLocatorRule.java:134)
      at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
      at com.sun.jersey.server.impl.uri.rules.SubLocatorRule.accept(SubLocatorRule.java:134)
      at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
      at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
      at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
      at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
      at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1469)
      at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1400)
      at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1349)
      at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1339)
      at com.sun.jersey.server.impl.container.grizzly.GrizzlyContainer._service(GrizzlyContainer.java:182)
      at com.sun.jersey.server.impl.container.grizzly.GrizzlyContainer.service(GrizzlyContainer.java:147)
      at org.glassfish.admin.rest.adapter.RestAdapter.service(RestAdapter.java:184)
      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:662)
      Caused by: javassist.CannotCompileException: by java.lang.NoClassDefFoundError: test/war1/Ejb
      at org.jboss.weld.util.bytecode.ClassFileUtils.toClass(ClassFileUtils.java:117)
      at org.jboss.weld.bean.proxy.ProxyFactory.createProxyClass(ProxyFactory.java:374)
      at org.jboss.weld.bean.proxy.ProxyFactory.getProxyClass(ProxyFactory.java:255)
      ... 60 more
      Caused by: java.lang.NoClassDefFoundError: test/war1/Ejb
      at java.lang.ClassLoader.defineClass1(Native Method)
      at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
      at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
      at sun.reflect.GeneratedMethodAccessor27.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      at java.lang.reflect.Method.invoke(Method.java:597)
      at org.jboss.weld.util.bytecode.ClassFileUtils.toClass2(ClassFileUtils.java:143)
      at org.jboss.weld.util.bytecode.ClassFileUtils.toClass(ClassFileUtils.java:109)
      ... 62 more
      Caused by: java.lang.ClassNotFoundException: test.war1.Ejb
      at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1519)
      at org.glassfish.web.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1369)
      ... 70 more

      It happens when there are several CDI-enabled modules within EAR and one of them has EJB with an interceptor. When the interceptor is removed tha application deploys correctly.
      I've attached sample application (EAR), server log and maven project used to create the application.

        Activity

        Hide
        Hong Zhang added a comment -

        assign to cdi team for initial evaluation

        Show
        Hong Zhang added a comment - assign to cdi team for initial evaluation
        Hide
        titmus added a comment -

        The issue seems to be caused by the fact that ProxyServices used by weld to obtain a class loader for proxied classes is only passed the class which is not sufficient in applications using multiple different class loaders (like an EAR application) - it is somewhat related to https://issues.jboss.org/browse/WELD-781
        The current implemetnation of ProxyServices (the class org.glassfish.weld.services.ProxyServicesImpl in weld-intergration module) always returns current thread context class loader.
        The BeanDeploymentArchiveImpl class has workaround for bug WELD-781 but it is only working while calling deployBeans method on BeanDeployment. It sets TCCL to class loader correct for currently deployed archive and after that TCCL is set to class loader of whichever archive was deployed last and is used by ProxyServices when afterBeanDiscovery method is called on BeanDeployment.
        In this situation TCCL is set to war2 class loader and therefore class test.war1.Ejb could not be found beacuse it is located in war1.
        To correctly handle this situation weld should provide information about bean''s deployment archive to the ProxyServices.

        I created a workaround for this. I register appropriate class loaders for discovered beans classess in ProxyServicesImpl which are then returned to the Weld. Because classes are matched by name it would not correctly handle situation when classes with the same package and name are located in different deployment archives (but it is not handled correctly by GlassFish anyway - see GLASSFISH-18204).
        A patch implementing the workaround is attached as GLASSFISH-18028.patch

        Show
        titmus added a comment - The issue seems to be caused by the fact that ProxyServices used by weld to obtain a class loader for proxied classes is only passed the class which is not sufficient in applications using multiple different class loaders (like an EAR application) - it is somewhat related to https://issues.jboss.org/browse/WELD-781 The current implemetnation of ProxyServices (the class org.glassfish.weld.services.ProxyServicesImpl in weld-intergration module) always returns current thread context class loader. The BeanDeploymentArchiveImpl class has workaround for bug WELD-781 but it is only working while calling deployBeans method on BeanDeployment. It sets TCCL to class loader correct for currently deployed archive and after that TCCL is set to class loader of whichever archive was deployed last and is used by ProxyServices when afterBeanDiscovery method is called on BeanDeployment. In this situation TCCL is set to war2 class loader and therefore class test.war1.Ejb could not be found beacuse it is located in war1. To correctly handle this situation weld should provide information about bean''s deployment archive to the ProxyServices. I created a workaround for this. I register appropriate class loaders for discovered beans classess in ProxyServicesImpl which are then returned to the Weld. Because classes are matched by name it would not correctly handle situation when classes with the same package and name are located in different deployment archives (but it is not handled correctly by GlassFish anyway - see GLASSFISH-18204 ). A patch implementing the workaround is attached as GLASSFISH-18028 .patch
        Hide
        Sivakumar Thyagarajan added a comment -

        Thanks for your detailed evaluation notes. As you rightly point out, the correct fix for this issue is through a fix for WELD-781 and having the Weld integration SPI provide the bean's deployment archive while trying to load a Proxy. We are working with the Weld team to get this integration SPI and hence I would like to wait for that. As you said the proposed patch is also a workaround and wouldn't for all cases. The patch also appears to use reflection to obtain the bean deployments and that may not be stable as it is not part of the Weld integration SPI. I will track WELD-781 and would request it to be included in the Weld 1.2.0 timeline.

        Show
        Sivakumar Thyagarajan added a comment - Thanks for your detailed evaluation notes. As you rightly point out, the correct fix for this issue is through a fix for WELD-781 and having the Weld integration SPI provide the bean's deployment archive while trying to load a Proxy. We are working with the Weld team to get this integration SPI and hence I would like to wait for that. As you said the proposed patch is also a workaround and wouldn't for all cases. The patch also appears to use reflection to obtain the bean deployments and that may not be stable as it is not part of the Weld integration SPI. I will track WELD-781 and would request it to be included in the Weld 1.2.0 timeline.
        Hide
        jjsnyder83 added a comment -

        I have tested this with the latest integrations with Weld and the application deploys successfully.

        Show
        jjsnyder83 added a comment - I have tested this with the latest integrations with Weld and the application deploys successfully.

          People

          • Assignee:
            jjsnyder83
            Reporter:
            titmus
          • Votes:
            2 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: