3 Replies Latest reply on Dec 20, 2012 11:00 AM by ron_sigal

    Injecting across lib and classes in a war

    ron_sigal

      Hi,

       

      I set out to write some Resteasy tests in which injections occur across ear, jar, and war boundaries, and I've run into a problem with my first test, the simple case with classes and jars in a war.  I have a JAX-RS resource:

      @Path("modules")

      public class TestResource

      {  

         @Inject

         private Injectable injectable;

       

         @PostConstruct

         public void pc()

         {

            System.out.println("injectable: " + injectable);

         }

        

         @GET

         @Path("test")

         public Response test()

         {

            System.out.println("injectable: "  + injectable);

            System.out.println("Injectable classloader:   " + Injectable.class.getClassLoader());

            System.out.println("TestResource classloader: " + TestResource.class.getClassLoader());

            return (injectable != null) ? Response.ok().build() : Response.serverError().build();

         }

      }

      and a class to be injected:

      public class Injectable

      {

      }

      I have two versions:

       

      1. TestResource is in /classes and Injectable is in a jar in /lib:

       

         @Deployment

         public static Archive<?> createTestArchive()

         {

            JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "test.jar")

                  .addClasses(Injectable.class)

                  ;

            WebArchive war = ShrinkWrap.create(WebArchive.class, "resteasy-cdi-ejb-test.war")

                  .addClasses(JaxRsActivator.class)

                  .addClasses(TestResource.class)

                  .addAsLibrary(jar)

                  .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");

            System.out.println(jar.toString(true));

            System.out.println(war.toString(true));

            return war;

         }

      In this case I get the exception

      Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [Injectable] with qualifiers [@Default] at injection point [[field] @Inject private org.jboss.resteasy.cdi.modules.TestResource.injectable]

      When I turn on DEBUG level logging for Weld, I see that a managed bean has been created for TestResource:

      18:59:56,934 DEBUG [org.jboss.weld.Bootstrap] (MSC service thread 1-16) WELD-000106 Bean: Managed Bean [class org.jboss.resteasy.cdi.modules.TestResource] with qualifiers [@Any @Default]

      but there is none for Injectable.

       

      2. TestResource is in a jar in /lib and Injectable is in /classes:

         @Deployment

         public static Archive<?> createTestArchive()

         {

            JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "test.jar")

                  .addClasses(TestResource.class)

                  ;

            WebArchive war = ShrinkWrap.create(WebArchive.class, "resteasy-cdi-ejb-test.war")

                  .addClasses(JaxRsActivator.class)

                  .addClasses(Injectable.class)

                  .addAsLibrary(jar)

                  .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");

            System.out.println(jar.toString(true));

            System.out.println(war.toString(true));

            return war;

         }

      In this case Weld doesn't complain, but when the test runs, injectable is null.  Also, I see that a managed bean has been created for Injectable:

      18:59:53,368 DEBUG [org.jboss.weld.Bootstrap] (MSC service thread 1-4) WELD-000106 Bean: Managed Bean [class org.jboss.resteasy.cdi.modules.Injectable] with qualifiers [@Any @Default]

      but not for TestResource.

       

      So, in each case, the class in /classes is getting processed as a bean, and the class in the jar is not.

       

      By the way, as you would expect, the same classloader is being used for the two classes:

      19:20:07,829 INFO  [stdout] (http--127.0.0.1-8080-3) Injectable classloader:         ModuleClassLoader for Module "deployment.resteasy-cdi-ejb-test.war:main" from Service Module Loader

      19:20:07,829 INFO  [stdout] (http--127.0.0.1-8080-3) TestResource classloader: ModuleClassLoader for Module "deployment.resteasy-cdi-ejb-test.war:main" from Service Module Loader

      Any ideas?

       

      -Ron