10 Replies Latest reply on Jul 18, 2012 9:07 PM by khooke

    JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean

    khooke

      I have a JAX-RS class that takes an incoming POST and then calls a method on an injected EJB. Unless the JAX-RS class is annotated as a SessionBean itself, it appears the @EJB annotation is ignored and the dependency is never injected (the property is null).

       

      The EE6 tutorial implies that you need to annotate the JAX-RS class with @RequestScoped so that it can support CDI injections, but by itself this doesn't work on AS7

      http://docs.oracle.com/javaee/6/tutorial/doc/gkncy.html

       

      This approach does not work (queueService is null):

      @Path("queue")
      @RequestScoped
      public class QueueInputWS {
      
           @EJB
           private QueueMessageService queueService;
      ,...
      }
      

      But this does work (queueService gets set):

      @Path("queue")
      @Stateless
      public class QueueInputWS {
      
           @EJB
           private QueueMessageService queueService;
      ...
      }
      

       

      Thoughts? Is this a bug, or is it a requirement for JAX-RS classes to also be SessionBeans in order to use CDI?

       

      Thanks! Kevin

        • 1. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
          ctomc

          Hi,

           

          @EJB is not CDI injection. @EJB only works for ejb session beans

           

          but it should work for you if you would use @Inject instead of @EJB.

           

           

          --

          tomaz

          • 2. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
            khooke

            Does the JAX-RS class need to be annotated with anything to make the @Inject work? I've tried just adding it to the JAX-RS class like this, but the property does not get set:

            @Path("queue")
            public class QueueInputWS {
            
                 @Inject
                 private QueueMessageService queueService;
            ...
            

            I've also tried adding @RequestScoped, and/or @Stateless, but neither of those make it work either - the property is always null? It only seems to get set if I use @EJB together with @Stateless - is the correct way to use CDI together with JAX-RS classes?.

            • 3. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
              sfcoy

              The container is required to support the @Resource, @Resources, @EJB, @EJBs, @WebServiceRef, @WebServiceRefs, @PersistenceContext, @PersistenceContexts, @PersistenceUnit and @PersistenceUnits resource injection annotations (the same as for servlets, listeners and filters).

               

              Therefore, there must be something else going on.

               

              How is your service packaged and deployed?

              • 4. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
                sfcoy

                and does your web.xml contain:

                 

                {code:xml}    <servlet-mapping>

                        <servlet-name>javax.ws.rs.core.Application</servlet-name>

                        <url-pattern>/rest/*</url-pattern>

                    </servlet-mapping>{code}

                 

                ?

                • 5. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
                  ctomc

                  Stephen,

                   

                  there is no need for that

                   

                  you can achive the same with:

                   

                  @ApplicationPath("/rest")

                  public class RestEasyBootstrap extends Application {

                   

                  }

                  (name of the class is irrelevant)

                   

                  --

                  tomaz

                  • 6. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
                    khooke

                    It's packaged as just 1 war containing the JAX-RS class which calls a method on an @Stateless bean to post a message into a queue. The project is a maven project.

                     

                    I have the following in my web.xml:

                     

                    <servlet>

                        <servlet-name>javax.ws.rs.core.Application</servlet-name>

                        <load-on-startup>1</load-on-startup>

                    </servlet>

                    <servlet-mapping>

                        <servlet-name>javax.ws.rs.core.Application</servlet-name>

                        <url-pattern>/ws/*</url-pattern>

                    </servlet-mapping>

                    • 7. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
                      jaikiran

                      Looks like the injection in that JAX-RS resource isn't handled correctly. Can you try changing it to:

                       

                      @Path("queue")
                      @RequestScoped
                      public class QueueInputWS {
                      
                           @EJB (lookup="TheJNDINameOfTheBean")
                           private QueueMessageService queueService;
                      ,...
                      }
                      

                       

                      You can find the JNDI name of the QueueMessageService logged in the server logs. If that doesn't work, you can even try:

                       

                      @EJB(mappedName="TheJNDINameOfTheBean")

                      • 8. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
                        khooke

                        Still no good - I tried both lookup="jndi name" and mappedName="jndi name" and the bean is still not injected. Is this only occuring in my code, or have other people ran into this as well (i.e. is it a bug?)

                         

                        I can commit the code to GitHub if you've time to pull it and take a look? It's pretty simple, and it's nothing more than what I've described above at this point, I started this as just a PoC to show a JAX-RS class fronting a Session bean that publishes messages to a queue.

                        • 9. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
                          khooke

                          Thinking I might have done something odd to my project config, I created a new project and I have two classes, simialr to the example above, and I still can't get it to work, so either I'm missing something fundamental, or this is a bug with JBoss AS7.1.0's implmentation of JAX-RS and/or CDI.

                           

                          Here's my two test classes:

                          package kh.jaxrstest.ws;

                           

                          import javax.ejb.EJB;

                          import javax.enterprise.context.RequestScoped;

                          import javax.ws.rs.GET;

                          import javax.ws.rs.Path;

                           

                          import kh.jaxrstest.service.TestService;

                           

                          @Path("test")

                          @RequestScoped

                          public class TestJAXRSWebService {

                             

                              @EJB

                              private TestService testService;

                             

                              @GET

                              public void testGet()

                              {

                                  System.out.println("ws GET called");

                                  testService.doSomething();

                              }

                             

                             

                          }

                           

                          Here's the session bean:

                          package kh.jaxrstest.service;

                           

                          import javax.ejb.Stateless;

                           

                          @Stateless

                          public class TestService {

                           

                              public TestService() {

                              }

                           

                              public void doSomething()

                              {

                                  System.out.println("session bean doSomething() called");

                              }

                          }

                           

                          I've configured JAX-RS via web.xml:

                          <web-app xmlns="http://java.sun.com/xml/ns/javaee"

                                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

                                xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

                                version="3.0">

                           

                          <servlet>

                              <servlet-name>javax.ws.rs.core.Application</servlet-name>

                              <load-on-startup>1</load-on-startup>

                          </servlet>

                          <servlet-mapping>

                              <servlet-name>javax.ws.rs.core.Application</servlet-name>

                              <url-pattern>/ws/*</url-pattern>

                          </servlet-mapping>

                          </web-app>

                           

                          and I've also tried the no xml approach with an init class:

                          package kh.jaxrstest.ws;

                           

                          import javax.ws.rs.ApplicationPath;

                          import javax.ws.rs.core.Application;

                           

                          @ApplicationPath("/ws")

                          public class JaxRsInit extends Application {

                          }

                           

                          Still no good - in the TestJAXRSWebService JAX-RS class, when testGet() is called when I hit /ws/test I get a NPE on this line:

                          testService.doSomething();

                           

                          since testService has not been injected.

                           

                          Any thoughts?

                          • 10. Re: JAX-RS class on AS7 does not get EJB dependencies injected unless annotated as a SessionBean
                            khooke

                            If you annotate the JAX-RS class with @ManagedBean then the injections work as expected. I can go with this for now. Although I think it's a bug that @RequestScoped does not work.