users@jersey.java.net

A bug from Jersey 1.0

From: ÂíÁÖ <ant_miracle_at_hotmail.com>
Date: Tue, 28 Oct 2008 20:00:36 +0800

Dear all,

    I don't know whether this letter will be received, if someone read this letter please reply to me. thanks!

    I found a bug from Jersey 1.0. if using any method to request a resource and that the result will be forward to a JSP file,
then found that all the value setted to the response object will be lost. after check the source code found problem as bellow:

Source code from "com.sun.jersey.impl.application.WebApplicationImpl" in handleRequest method

    public void handleRequest(ContainerRequest request, ContainerResponseWriter responseWriter)
            throws IOException {
        final ContainerResponse response = new ContainerResponse(
                this,
                request,
                responseWriter);
        handleRequest(request, response);
    }

as above we see that HttpServletResponse is wrapped by the ContainerResponseWriter object. for invoking method of
" public void handleRequest(ContainerRequest request, ContainerResponse response) throws IOException " ContainerResponse wraps the
ContainerResponseWriter again.
so here I found the problem that the value setted in ContainerResponse object not save back to orginal HttpServletRequest..

finally it cause to com.sun.jersey.impl.container.servlet.JSPTemplateProcessor 's method named "writeTo" can only get a unchaged HttpServletResponse instance.

        
    public void writeTo(String resolvedPath, Object model, OutputStream out) throws IOException {
        RequestDispatcher d = servletContext.getRequestDispatcher(resolvedPath);
        if (d == null) {
            throw new ContainerException("No request dispatcher for: " + resolvedPath);
        }
                
        d = new RequestDispatcherWrapper(d, ui.getMatchedResources().get(0), model);
        
        try {
            // Matt mark here. actually the HttpServletResponse get from current thread object is unchanged.
            d.forward(requestInvoker.get(), responseInvoker.get());
        } catch (Exception e) {
            e.printStackTrace();
            throw new ContainerException(e);
        }
    }


Here I add one line code to solve this problem
com.sun.jersey.impl.application.WebApplicationImpl


    public void handleRequest(ContainerRequest request, ContainerResponse response) throws IOException {
        try {
            final WebApplicationContext localContext = new
                    WebApplicationContext(this, request, response);
            context.set(localContext);
                
                    //...
            
        try {
            for (ContainerResponseFilter f : responseFilters)
                response = f.filter(request, response);
  
            
        } catch (WebApplicationException e) {
            mapWebApplicationException(e, response);
        } catch (RuntimeException e) {
            if (!mapException(e, response)) {
                context.set(null);
                throw e;
            }
        }
        //matt add here
        //before write method save the response header value back to store HttpServletResoponse object
         response.getContainerResponseWriter().writeStatusAndHeaders(-1, response);

        try {
            response.write();
        } catch (WebApplicationException e) {
            if (response.isCommitted()) {
                throw e;
            } else {
                mapWebApplicationException(e, response);
                response.write();
            }
        } finally {
            context.set(null);
        }
    }

 Your reply is expecting!



Yours Matt!
2008-10-28 from beijin China.