3 Replies Latest reply on Sep 3, 2010 2:37 PM by Marcel Kolsteren

    injection into a programmatically registered servlet

    Marcel Kolsteren Apprentice

      Injection doesn't seem to take place in a servlet that is registered programmatically.

      In order to demonstrate this issue, I created an Arquillian test for a managed JBoss M4 application server. The test deploys a war-file that contains two servlets. Both servlets refer to the same servlet class. The servlet class is very simple: it has a field into which a request scoped bean is injected, and it reports to the client whether or not this field contains a null value. The first servlet is defined in the web.xml file, the second servlet is registered programmatically by calling ServletContext.addServlet. The test cases show that the first servlet works correctly. However, the second servlet detects a null value in the field that should contain an injected instance of the request scoped bean.

      This seems to be a bug. Or did I miss something in the CDI spec?

      Steps for reproduction:



      • unpack the attached zip file

      • export JAVA_HOME = <home of your JDK>

      • export JBOSS_HOME = <root directory of your JBoss 6 M4 server>

      • mvn test



      See also Thread on the JBoss AS forum.

        • 1. Re: injection into a programmatically registered servlet
          Jan Groth Novice

          Marcel, can you please ask this in the Weld user forum here http://seamframework.org/Community/WeldUsersForum? Weld developers hang out there.

          I'm certainly not one of those, so consider it my two cents:


          I'm wondering when (and by whom) this class is instantiated:



          package nl.meandi.examples;
          
          import java.io.IOException;
          
          import javax.inject.Inject;
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          
          public class TestServlet extends HttpServlet {
               private static final long serialVersionUID = -2831626634018329617L;
          
               @Inject
               RequestScopedBean requestScopedBean;
          
               @Override
               protected void doGet(HttpServletRequest req, HttpServletResponse resp)
                         throws ServletException, IOException {
                    if (requestScopedBean == null) {
                         resp.setContentType("text/plain");
                         resp.getWriter().print("NOT_OK");
                         resp.flushBuffer();
                    } else {
                         resp.setContentType("text/plain");
                         resp.getWriter().print("OK");
                         resp.flushBuffer();
                    }
               }
          }



          The question I'm trying to raise: Is TestServlet a managed bean / contextual component in both cases?


          Looking forward to learn about the answer,


          Jan



          • 2. Re: injection into a programmatically registered servlet
            Marcel Kolsteren Apprentice

            Hi Jan,


            The TestServlet is instantiated twice:



            • In web.xml, a servlet named TestServlet1 is defined, referring to the class TestServlet.

            • In the ServletInstaller class, which listens to the servlet context initialization event, the TestServlet is instantiated programmatically, by calling addServlet on the servlet context. This results in a servlet named TestServlet2.



            In both cases, TestServlet is not a managed bean, it's not contextual, and it doesn't have a scope. It is an instance one of a Java EE component types for which dependency injection can be used. Quote from the CDI spec, section 5.5:



            The container is also required to perform dependency injection whenever it instantiates any of the following non-contextual objects:
            non-contextual instances of session beans (...), non-contextual instances of managed beans, and instances of any other Java EE component class supporting injection.

            Servlets are an example of the last mentioned category of injection-capable components. I hope this cleared things up for you.


            Marcel

            • 3. Re: injection into a programmatically registered servlet
              Marcel Kolsteren Apprentice

              I talked with Pete Muir and Nicklas Karlsson about this issue. Because the spec doesn't seem to contain a hard requirement concerning this subject, I submitted a feature request (instead of a bug report):

              JBAS-8387

              According to Pete, it's certainly possible to support this feature.