8 Replies Latest reply on Jan 17, 2011 4:28 PM by Dan Allen

    Can't make injection work in a Servlet with Jetty 6

    Antonio Goncalves Newbie

      Hi,

      Weld 1.1.0.CR1
      Jetty 6.1.26

      I have a very simple Servlet injecting a bean with @Inject :


      public class MainServlet25 extends HttpServlet {

          @Inject
          Hello hello;

          @Override
          protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
              resp.setContentType("text/html");
              PrintWriter out = resp.getWriter();
              out.println("<HTML>");
              out.println("<HEAD><TITLE>Bootstrap CDI in Tomcat</TITLE></HEAD>");
              out.println("<BODY>");
              out.println(saySomething());
              out.println("</BODY>");
              out.println("</HTML>");
              out.close();
          }

          public String saySomething() {
              return hello.sayHelloWorld();
          }
      }


      public class Hello {

          public String sayHelloWorld() {
              return "Hello " + world.sayWorld();
          }
      }


      I've followed the instruction described in 18.3.2 (http://docs.jboss.org/weld/reference/latest/en-US/html_single/d0e5297) but I have a NPE when invoking the servlet. I've copied the same jett-web.xml (for injection), the jetty-env.xml, the listener in web.xml, the empty beans.xml file from the Weld documentation... but it doesn't work. Here is the stack trace :


      2011-01-09 22:26:43.871:WARN::/bootstrapping-servlet25-jetty/mainServlet
      java.lang.NullPointerException
              at org.antoniogoncalves.cdi.bootstrapping.servlet.MainServlet25.saySomething(MainServlet25.java:33)
              at org.antoniogoncalves.cdi.bootstrapping.servlet.MainServlet25.service(MainServlet25.java:26)
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
              at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
              at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:401)
              at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
              at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
              at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
              at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)
              at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
              at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
              at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
              at org.mortbay.jetty.Server.handle(Server.java:326)
              at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
              at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:928)
              at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
              at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
              at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
              at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
              at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)



      Any idea ?
      Thanks,
      Antonio




        • 1. Re: Can't make injection work in a Servlet with Jetty 6
          Antonio Goncalves Newbie

          Hum, formatting didn't work, let's try again.


          Weld 1.1.0.CR1
          Jetty 6.1.26


          I have a very simple Servlet injecting a bean with @Inject :




          public class MainServlet25 extends HttpServlet {
          
              @Inject
              Hello hello;
          
              @Override
              protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
                  resp.setContentType("text/html");
                  PrintWriter out = resp.getWriter();
                  out.println("<HTML>");
                  out.println("<HEAD><TITLE>Bootstrap CDI in Jetty</TITLE></HEAD>");
                  out.println("<BODY>");
                  out.println(saySomething());
                  out.println("</BODY>");
                  out.println("</HTML>");
                  out.close();
              }
          
              public String saySomething() {
                  return hello.sayHelloWorld();
              }
          }
          
          public class Hello {
              
              public String sayHelloWorld() {
                  return "Hello " + world.sayWorld();
              }
          }






          I've followed the instruction described in 18.3.2 (http://docs.jboss.org/weld/reference/latest/en-US) but I have a NPE when invoking the servlet. I've copied the same jett-web.xml (for injection), the jetty-env.xml, the listener in web.xml, the empty beans.xml file from the Weld documentation... but it doesn't work.


          Here is the stack trace :




          java.lang.NullPointerException
                  at org.antoniogoncalves.cdi.bootstrapping.servlet.MainServlet25.saySomething(MainServlet25.java:33)
                  at org.antoniogoncalves.cdi.bootstrapping.servlet.MainServlet25.service(MainServlet25.java:26)
                  at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
                  at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
                  at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:401)
                  at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
                  at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
                  at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:766)
                  at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:450)
                  at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
                  at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
                  at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
                  at org.mortbay.jetty.Server.handle(Server.java:326)
                  at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
                  at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:928)
                  at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:549)
                  at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:212)
                  at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
                  at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
                  at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
          




          I also followed the instruction to make it work with Tomcat 6.x and it worked fine. Any idea why it doesn't with Jetty 6.x ?


          Thanks,
          Antonio

          • 2. Re: Can't make injection work in a Servlet with Jetty 6
            Dan Allen Master

            I thought this problem was the same as the one I encountered, but as it turns out I can't get past the same error you are encountering, so I guess not.


            This looks like a bug in Weld. It's either a problem in the Weld code, or it's a problem of documentation. Either way, it's a problem.


            I do know that at some point Jetty changed how it registered JNDI resources (it's already like black magic, now it's black magic with a twist). Here's the jetty-env.xml that I use with Jetty 6.1.21 in Seam Wicket:


               <New id="BeanManager" class="org.mortbay.jetty.plus.naming.EnvEntry">
                  <Arg><Ref id="webAppCtx"/></Arg>
                  <Arg>BeanManager</Arg>
                  <Arg>
                     <New class="javax.naming.Reference">
                        <Arg>javax.enterprise.inject.spi.BeanManager</Arg>
                        <Arg>org.jboss.weld.resources.ManagerObjectFactory</Arg>
                        <Arg/>
                     </New>
                  </Arg>
                  <Arg type="boolean">true</Arg>
               </New>
            



            Note the different class name and extra parameter.


            I also recommend putting beans.xml in both src/main/webapp/WEB-INF and src/main/resources/META-INF when using the Jetty Maven plugin. Depending on the circumstances (in-place vs not), it can't see one or the other.


            If you are just looking to get something working, and aren't tied to Jetty 6.x, I highly recommend Jetty 8, which is now under the Eclipse banner. It is in much better shape as a project and it behaves a heck of a lot better. We have full support for it as soon as this patch is merged: https://issues.jboss.org/browse/WELD-729

            • 4. Re: Can't make injection work in a Servlet with Jetty 6
              Antonio Goncalves Newbie

              Thanks Dan for your prompt response. I've tried using the same jetty-env.xml, copying the beans.xml file in both locations, using Jetty 6.1.21 (instead of the 6.1.26 I was using)... but I still have the same problem. I will follow your advice and give Jetty 8 a try as soon as the patch is merged... and then I'll update my post on how to bootstrap Weld (http://agoncal.wordpress.com/2011/01/12/bootstrapping-cdi-in-several-environments/).


              Thanks

              • 5. Re: Can't make injection work in a Servlet with Jetty 6
                Dan Allen Master

                https://issues.jboss.org/browse/WELD-823


                Clearly we are missing test coverage for this use case.


                Antonio, if you have the bandwidth, you may want to consider throwing this in a debugger to see what's going on. With all the sources in the Maven repo, you should be able to step into Jetty easily.

                • 6. Re: Can't make injection work in a Servlet with Jetty 6
                  Pete Muir Master

                  We do have tests for this, and it is working fine. The Weld docs incorrectly state that jetty-web.xml belongs in META-INF, when actually it belongs in WEB-INF.

                  • 7. Re: Can't make injection work in a Servlet with Jetty 6
                    Antonio Goncalves Newbie

                    Yes it woks with WEB-INF/jetty-web.xml.


                    Thanks,
                    Antonio

                    • 8. Re: Can't make injection work in a Servlet with Jetty 6
                      Dan Allen Master

                      Antonio Goncalves wrote on Jan 17, 2011 16:21:


                      Yes it woks with WEB-INF/jetty-web.xml.

                      Thanks,
                      Antonio


                      Excellent! Thanks for bringing this issue to light Antonio. Win!