12 Replies Latest reply on Dec 23, 2008 4:45 PM by Manuel Baehnisch

    NPE in SeamResourceServlet for delivering XML

    Manuel Baehnisch Newbie

      Hi,


      I'm working on a class in order to deploy it as a SeamResourceServlet. It will be used to provide flash with xml data by receiving xml from the request, computing it and writing the manipulated xml back to the response.


      @Scope(ScopeType.APPLICATION)
      @Name("flashCommunicationResource")
      public class FlashCommunicationResource extends AbstractResource {

              //
              // attributes
              //
              @Logger
              private static Log logger;

              @In(create = true, required = false)
              private FlashController flashController;


              @Override
              public String getResourcePath() {
                      return "/myresource";
              }

              @Override
              public void getResource(final HttpServletRequest request, final HttpServletResponse response)
                              throws ServletException, IOException {

                      new ContextualHttpServletRequest(request) {
                              @Override
                              public void process() throws IOException {
                                      doWork(request, response);
                              }
                      }.run();
              }

              private void doWork(HttpServletRequest request, HttpServletResponse response) {

                      InputStream instream = null;
                      OutputStream outstream = null;
                      try {
                              instream = request.getInputStream();
                              response.setContentType("text/xml");
                              outstream = response.getOutputStream();

                              logger.debug("type=" + type);
                              flashController.computeXmlInputAndWriteResult(instream, outstream);

                              outstream.flush();
                              outstream.close();
                              instream.close();
                      }
                      catch (IOException e) {
                              ...
                      }
              }
      }


      I checked the outstream by diverting it to System.out which looks perfect. But Seam crashes with the following NPE:


      java.lang.NullPointerException
              at org.jboss.seam.contexts.Contexts.destroy(Contexts.java:241)
              at org.jboss.seam.contexts.Lifecycle.endCall(Lifecycle.java:95)
              at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:122)
              at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:166)
              at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:102)
              at ....FlashCommunicationResource_$$_javassist_1.getResource(FlashCommunicationResource_$$_javassist_1.java)
              at org.jboss.seam.servlet.SeamResourceServlet.service(SeamResourceServlet.java:80)
              at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
              ....


      I'm fairly new to seam. Any ideas?
      Thanks allot in advance.
      Manuel

        • 1. Re: NPE in SeamResourceServlet for delivering XML
          Manuel Baehnisch Newbie

          Sorry for the weird looking code. Here it is reformatted:


          @Scope(ScopeType.APPLICATION) 
          @Name("flashCommunicationResource") 
          public class FlashCommunicationResource extends AbstractResource { 
          
               @Logger private static Log logger; 
          
               @In(create = true, required = false) 
               private FlashController flashController; 
          
               @Override 
               public String getResourcePath() { return "/myresource"; } 
          
               @Override public void getResource(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { 
          
                    new ContextualHttpServletRequest(request) 
                    { 
                         @Override public void process() throws IOException { 
                              doWork(request, response); } 
                    }.run(); 
               } 
          
               private void doWork(HttpServletRequest request, HttpServletResponse response) { 
                    InputStream instream = null; 
                    OutputStream outstream = null; 
                    try { 
                         instream = request.getInputStream(); 
                         response.setContentType("text/xml"); 
                         outstream = response.getOutputStream(); 
                         
                         flashController.computeXmlInputAndWriteResult(instream, outstream); 
                         outstream.flush(); 
                         outstream.close(); 
                         instream.close(); 
                    } catch (IOException e) { ... } 
               }
          }




          java.lang.NullPointerException 
          at org.jboss.seam.contexts.Contexts.destroy(Contexts.java:241) 
          at org.jboss.seam.contexts.Lifecycle.endCall(Lifecycle.java:95) 
          at org.jboss.seam.intercept.RootInterceptor.invoke(RootInterceptor.java:122) 
          at org.jboss.seam.intercept.JavaBeanInterceptor.interceptInvocation(JavaBeanInterceptor.java:166) 
          at org.jboss.seam.intercept.JavaBeanInterceptor.invoke(JavaBeanInterceptor.java:102) 
          at ....FlashCommunicationResource_$$_javassist_1.getResource(FlashCommunicationResource_$$_javassist_1.java) 
          at org.jboss.seam.servlet.SeamResourceServlet.service(SeamResourceServlet.java:80) 
          at javax.servlet.http.HttpServlet.service(HttpServlet.java:803) 
          ....


          • 2. Re: NPE in SeamResourceServlet for delivering XML
            Shane Bryzak Master

            Are you sure the request is not already wrapped by the ContextFilter ?

            • 3. Re: NPE in SeamResourceServlet for delivering XML
              Manuel Baehnisch Newbie

              I'm new to seam, so I'm not quite sure what you mean. I found this page (here) and thought I adapated the code shown correctly. Might there be something wrong with my code?


              I checked the web.xml and the Seam ContextFilter was not configured yet. I configured it in the web.xml with the url-pattern '/seam/resource/*' and now get the following exception:


              09:05:36,602 WARN  [ContextualHttpServletRequest] ended request due to exception
              java.lang.IllegalStateException: No active event context
                   at org.jboss.seam.core.Manager.instance(Manager.java:272)
                   at org.jboss.seam.servlet.ContextualHttpServletRequest.run(ContextualHttpServletRequest.java:55)
                   at org.jboss.seam.web.ContextFilter.doFilter(ContextFilter.java:37)
                   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
                   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
                   at org.jboss.seam.servlet.SeamFilter$FilterChainImpl.doFilter(SeamFilter.java:83)
                   at org.jboss.seam.debug.hot.HotDeployFilter.doFilter(HotDeployFilter.java:51)
                      ...



              Any help or idea is much appreciated.

              • 4. Re: NPE in SeamResourceServlet for delivering XML
                Shane Bryzak Master

                Do you already have org.jboss.seam.servlet.SeamFilter configured in web.xml?  If so, you don't need to configure ContextFilter explicitly.  I recommend that you try removing the ContextualHttpRequest wrapper from your resource code.

                • 5. Re: NPE in SeamResourceServlet for delivering XML
                  Shane Bryzak Master

                  Oops, I mean ContextualHttpServletRequest.

                  • 6. Re: NPE in SeamResourceServlet for delivering XML
                    Manuel Baehnisch Newbie

                    Yes, the Seam Filter is configured to filter all requests (/*). I removed wrapping the request in a ContextualHttpServletRequest and the NPE was solved. Btw: The original request is of the type org.jboss.seam.web.IdentityRequestWrapper.


                    Apparently now the request seems not to be part of the seam context. Within my flashController I have a user object injected which gets initialized with each session start. The class that performs the initalization is annotated with


                     @Scope(ScopeType.SESSION)
                     @Startup



                    and outjects the user object into the session. From the log I can tell that it is definatly called. So the user objects must exist. It seems that my request is not part of the seam context because I get a


                    @In attribute requires non-null value




                    Any ideas?

                    • 7. Re: NPE in SeamResourceServlet for delivering XML
                      Shane Bryzak Master

                      It should be easy enough to tell if the Seam contexts have been initialized for your request - using a debugger, set a breakpoint in your method and then see if Contexts.getSessionContext() returns a value.

                      • 8. Re: NPE in SeamResourceServlet for delivering XML
                        Manuel Baehnisch Newbie

                        If I wrap the request into the ContextualHttpServletRequest I have the same SessionContext object available in the class that creates/outjects my user object and within the FlashController class. So I assume wrapping the request tells Seam to use the same context. 


                        If I remove wrapping the request there is only a BasicContext available in the FlashController and thus the user object is not injected. Which makes sense as the context is not the same.


                        Is there a way to tell seam that the normal/not wrapped request should run in the same SessionContext? Or do you see another solution for the NPE within the wrapped request?


                        Thanks so far.


                        • 9. Re: NPE in SeamResourceServlet for delivering XML
                          Ronald van Kuijk Apprentice

                          Shane Bryzak wrote on Nov 11, 2008 10:17:


                          Do you already have org.jboss.seam.servlet.SeamFilter configured in web.xml?  If so, you don't need to configure ContextFilter explicitly.


                          TTTTTTTHHHHHHHHHHHHHHHHAAAAAAAAAAAAAAANNNNNNNNNNKKKKKKKKKKKKKSSSSSSSSSSSSSS


                          This was a left-over in my components.xml for trying to get a custom servletfilter to work with seam (so an xforms engine can be used in seam) The 'no event context' error does not occur if you are in .seam pages. Only if you use custom pages (.xform) you get this error...

                          • 10. Re: NPE in SeamResourceServlet for delivering XML
                            Manuel Baehnisch Newbie

                            I've already tried that before. When I add the @BypassInterceptors annotation into my resource the Seam Component flashController is not injected. Which in a way makes sense because the api already explains that the annotation will disable interception of calls to that seam component (here my resource).


                            Do I need to instantiate the FlashController myself? That doesn't really sound right to me, because I hoped that was something seam would do for me. Or do I need to declare which type/methods it should bypass and which not? And if so, which should I add?


                            Any ideas? Thanks allot.


                            Manuel

                            • 11. Re: NPE in SeamResourceServlet for delivering XML
                              Ronald van Kuijk Apprentice

                              The following works for me. The additional helper is needed with application scope, as is @BypassInterceptors on the filter.



                              my filter:



                              @Startup
                              @Scope(ScopeType.APPLICATION)
                              @Name("org.domain.TestFilter")
                              @BypassInterceptors
                              @Filter(within = "org.jboss.seam.web.ajax4jsfFilter")
                              public class TestFilter extends AbstractFilter {
                              
                                  @Logger
                                  private Log log;
                              
                                  @Override
                                  public void init(FilterConfig filterConfig) throws ServletException {
                                   super.init(filterConfig);
                                  }
                              
                                  @Destroy
                                  public void destroy() {
                                   log.debug("cleanups allocated resources");
                                  }
                              
                                  public void doFilter(final ServletRequest servletRequest,
                                       final ServletResponse servletResponse, final FilterChain filterChain)
                                       throws IOException, ServletException {
                              
                                   // make extension configurable
                                   String requestURL = ((HttpServletRequest) servletRequest).getRequestURL().toString(); 
                                   if (requestURL.endsWith(".xform")) {
                                       new ContextualHttpServletRequest(
                                            (HttpServletRequest) servletRequest) {
                              
                                        @Override
                                        public void process() throws Exception {
                              
                                            log.debug("Processing #0, requestURL);
                                            processRequest(servletRequest, servletResponse, filterChain);
                                            log.debug("Processed #0", requestURL);
                              
                                            filterChain.doFilter(servletRequest, servletResponse);
                                        }
                              
                                       }.run();
                              
                                       
                                       
                                   } else {
                                       log.debug("Ignoring #0", requestURL);
                                       filterChain.doFilter(servletRequest, servletResponse);
                                   }
                                   
                                   
                                  }
                              
                                  private void processRequest(ServletRequest servletRequest,
                                       ServletResponse servletResponse, FilterChain filterChain)
                                       throws IOException, ServletException {
                              
                              
                                   TestFilterHelper tfh = (TestFilterHelper) Component
                                        .getInstance("org.domain.TestFilterHelper");
                              
                                   tfh.handleSomething(servletRequest, servletResponse, filterChain);
                                  }
                              }




                              My helper:



                              @Name("org.domain.TestFilterHelper")
                              // Application scope is needed
                              @Scope(ScopeType.APPLICATION)
                              public class TestFilterHelper {
                              
                                  @Logger
                                  Log log;
                              
                                  // cannot have create=true
                                  @In(scope = ScopeType.CONVERSATION, value = "org.domain.NeededClass", required = false)
                                  NeededClass neededClass;
                              
                                  @Create
                                  public void onCreate() {
                                   log.info("TestFilterHelper created");
                              
                                  }
                              
                                  public void handleSomething(ServletRequest servletRequest,
                                       ServletResponse servletResponse, FilterChain filterChain)
                                       throws IOException, ServletException {
                              
                                   log.info("handleSomething(..,..,..)");
                                   if (neededClass == null) {
                                       log.info("neededClass == null, checking conversationId");
                              
                                       if (ConversationPropagation.instance().getConversationId() != null
                                            && Contexts.isConversationContextActive()) {
                              
                                        log.debug("There is a long running conversation... getting context and creating instance of component');
                                        neededClass = (NeededClass) Component.getInstance(
                                             "org.domain.NeededClass",
                                             ScopeType.CONVERSATION);
                                        log.debug("neededClass: #0", neededClass);
                              
                                       } else {
                                        log.debug("Silently ignoring the fact that there is no long conversationid");
                                        return;
                                       }
                              
                                   } else {
                                       log.info("We have an existing XFormsSession: #0", neededClass);
                                   }
                              
                                   neededClass.handleRequest();
                                  }



                              my 'NeededClass':



                              @AutoCreate
                              @Name("org.domain.NeededClass")
                              @Scope(ScopeType.CONVERSATION)
                              public class NeededClass implements Serializable {
                              
                                  private static final long serialVersionUID = 7610455116364472374L;
                                  
                                  @Logger
                                  Log log;
                              
                                  public synchronized void handleRequest() throws IOException {
                              
                                   log.info("Start handleRequest()");
                                   
                                      // do real work here or whatever        
                              
                                   log.info("End handleRequest()");
                                  }
                              
                                  


                              • 12. Re: NPE in SeamResourceServlet for delivering XML
                                Manuel Baehnisch Newbie

                                Hi Ronald,


                                so the basic difference is: You didn't inject the Helper Class but received it via Components.getInstance().


                                I tried that and it works. Actually a mistake I could've found out myself, right?! The injection didn't work because of the @BypassInterceptors and therefore the only way to get a component is via the Components.getInstance() method.


                                Cool. Thanks a million.


                                Manuel