4 Replies Latest reply on Oct 27, 2010 6:33 PM by Kabir Khan

    Issues with modular classloading

    Brian Stansberry Master

      I've been experimenting with deploying managed bean jars and with sars, and am finding some classloading related problems. These don't show up in the tests in the sar and managedbean modules, probably because those tests aren't using a modular classpath.

       

      First involves deploying a jar with managed beans:

       

      22:52:37,610 INFO  [deployment] Activating deployment: managedBeanDeployment.jar
      22:52:44,689 INFO  [managedbean] Starting managed bean service jboss.managed.bean.managedBeanDeployment_jar.TestBean
      23:03:53,377 ERROR [deployment] Caught exception handling update (param is 13fde2d1-661b-499f-87e4-c955493c4a56): org.jboss.msc.service.StartException in service service jboss.managed.bean.managedBeanDeployment_jar.TestBeanWithInjection: Failed to start service
          at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1037)
          at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_20]
          at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_20]
          at java.lang.Thread.run(Thread.java:637) [:1.6.0_20]
      Caused by: org.jboss.msc.inject.InjectionException: Injecting the wrong type (expected class org.jboss.as.deployment.managedbean.TestManagedBean, got class javax.naming.Reference)
          at org.jboss.msc.inject.CastingInjector.inject(CastingInjector.java:51)
          at org.jboss.msc.service.ServiceControllerImpl.doInject(ServiceControllerImpl.java:729)
          at org.jboss.msc.service.ServiceControllerImpl.access$1100(ServiceControllerImpl.java:122)
          at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:986)
          ... 3 more
      Caused by: java.lang.ClassCastException
          at java.lang.Class.cast(Class.java:2990) [:1.6.0_20]
          at org.jboss.msc.inject.CastingInjector.inject(CastingInjector.java:49)
          ... 6 more
      

       

      What's happening here is during start of a ManagedBeanService, an injection from a ResourceBinder is occuring. ResourceBinder.getValue() is doing a naming lookup. The lookup finds a LinkRef and tries to resolve it. Resolving it fails because the LinkRef points to a Reference. Reference has a classfactory "org.jboss.as.deployment.managedbean.container.ManagedBeanObjectFactory".  NamingManager tries to load that class and can't.

       

      Tricky bit here is the thread involved is an MSC start task thread, so it's not a user request thread where we can readily set the TCCL.

       

      The problem could be that we are doing this injection at this point in the first place? I haven't looked enough at how this service works to say.

       

      If the lookup actually needs to happen during the start task, then we need some more smarts to get the classloading right. Perhaps in ResourceBinder.getValue(), perhaps with a custom ObjectFactoryBuilder that can do modular classloading, perhaps...

        • 1. Re: Issues with modular classloading
          Brian Stansberry Master

          I'm pretty sure doing the lookup during the start task is incorrect. The way this works now, for a given managed bean type T, the ManagedBeanService<T> would have an instance of each @Resource bean injected as part of start(). Thereafter whenever ManagedBeanContainer.createInstance() is invoked, the same bean instance would be injected into the newly created bean. AIUI what should happen is createInstance() should result in a new naming lookup for each @Resource bean, which in turn would trigger creation of a new instance of that bean.

           

          I've opened https://jira.jboss.org/browse/JBAS-8513

          • 2. Re: Issues with modular classloading
            Brian Stansberry Master

            Another issue I'm seeing is deployment processor failures processing managed bean jars:

             

            14:11:52,800 INFO  [stdout] @javax.annotation.Resource(shareable=true, mappedName=, description=, name=, type=class java.lang.Object, authenticationType=CONTAINER) null
            14:11:52,800 INFO  [stdout] interface javax.annotation.Resource ClassLoader for Module "module:javax.annotation.api:main"
            14:11:52,801 ERROR [deployment] Caught exception handling update (param is f91250dd-121a-4c01-9407-1c91cb53e5cd): java.lang.NullPointerException
                at org.jboss.as.deployment.managedbean.processors.ManagedBeanAnnotationProcessor.processFieldResource(ManagedBeanAnnotationProcessor.java:295)
                at org.jboss.as.deployment.managedbean.processors.ManagedBeanAnnotationProcessor.processResources(ManagedBeanAnnotationProcessor.java:261)
                at org.jboss.as.deployment.managedbean.processors.ManagedBeanAnnotationProcessor.processDeployment(ManagedBeanAnnotationProcessor.java:125)
                at org.jboss.as.deployment.chain.DeploymentChainImpl.processDeployment(DeploymentChainImpl.java:60)
                at org.jboss.as.model.ServerDeploymentStartStopHandler.activate(ServerDeploymentStartStopHandler.java:191)
                at org.jboss.as.model.ServerDeploymentStartStopHandler.deploy(ServerDeploymentStartStopHandler.java:87)
                at org.jboss.as.model.ServerDeploymentStartStopHandler.deploy(ServerDeploymentStartStopHandler.java:71)
                at org.jboss.as.model.ServerDeploymentStartStopHandler.redeploy(ServerDeploymentStartStopHandler.java:117)
                at org.jboss.as.model.ServerModelDeploymentFullReplaceUpdate.applyUpdate(ServerModelDeploymentFullReplaceUpdate.java:75)
                at org.jboss.as.server.mgmt.ServerUpdateController$ServerModelUpdateTuple.applyUpdate(ServerUpdateController.java:387)
                at org.jboss.as.server.mgmt.ServerUpdateController$ServerModelUpdateTuple.access$200(ServerUpdateController.java:357)
                at org.jboss.as.server.mgmt.ServerUpdateController.applyUpdates(ServerUpdateController.java:182)
                at org.jboss.as.server.mgmt.ServerUpdateController.executeUpdates(ServerUpdateController.java:139)
                at org.jboss.as.server.mgmt.deployment.ServerDeploymentManagerImpl$2.run(ServerDeploymentManagerImpl.java:218)
                at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) [:1.6.0_20]
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) [:1.6.0_20]
                at java.lang.Thread.run(Thread.java:637) [:1.6.0_20]

             

             

            The NPE happens because a lookup in a Map<Class, Annotation> is unexpectedly returning null. It returns null because the Resource.class passed to the lookup is loaded from a different CL from the Resource.class that's a key in the map.  The first couple lines of logging above are some debug output I threw in; the first line shows the map key was loaded from the system CL while the param was loaded from a module.

             

            I think the problem here is the javax.annotation.api module includes classes that are in the 'system' module.

            • 4. Re: Issues with modular classloading
              Kabir Khan Master

              What seems to work for me in the managed bean demo example is to not import 'system' in the deployment's MANIFEST.MF.