Execute jsp in Spring controller and get response html

java, spring

Solution

Edit:

I ended up writing this bean (using `HtmlServlet*Response*Wrapper` :-)), I hope it could be useful for someone (thanks to: Reading ServletOutputStream to String)

(The viewResolver is autowired so it needs to be defined inside the the servlet context)

import java.io.IOException;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;

public class InternalRenderer {

    private final static String ENCODE = "UTF-8";

    @Autowired
    private ViewResolver viewResolver;

    public String evalView(HttpServletRequest request, HttpServletResponse response, Model model, Locale locale, String viewName) throws Exception {

        CustomHttpServletResponse customResponse = new CustomHttpServletResponse(response);

        View view = viewResolver.resolveViewName(viewName, locale);

        if(view != null){

            view.render(fillModelMap(model), request, customResponse);

            OutputStream os = customResponse.getOutputStream();

            return os.toString();

        }

        throw new Exception("no view found");
    }

    private Map<String, Object> fillModelMap(Model model) {

        if(model == null)
            return new HashMap<String,Object>();

        return model.asMap();
    }

    class CustomServletOutPutStream extends ServletOutputStream {

        private StringBuilder stringBuilder = new StringBuilder();

        @Override
        public String toString() {
            return stringBuilder.toString();
        }

        @Override
        public void write(int b) {
            stringBuilder.append(b);
        }

        @Override
        public void write(byte b[], int off, int len) throws IOException {
            stringBuilder.append(new String(b, off, len, ENCODE));
        }
    }

    class CustomHttpServletResponse extends HttpServletResponseWrapper {

        private ServletOutputStream outputStream;
        private PrintWriter printWriter;

        public CustomHttpServletResponse(HttpServletResponse response) throws UnsupportedEncodingException {
            super(response);

            this.outputStream = new CustomServletOutPutStream();
            this.printWriter = new PrintWriter(new OutputStreamWriter(outputStream, ENCODE));

        }

        @Override
        public ServletOutputStream getOutputStream() {
            return this.outputStream;
        }

        @Override
        public PrintWriter getWriter() throws IOException {
            return this.printWriter;
        }
    }

}

and you can call it like

    @Autowired
    InternalRenderer internalRenderer;

    @RequestMapping(value = "/internalRender")
    public void internalRender(HttpServletRequest request, HttpServletResponse response, Model model, Locale locale) throws Exception {

        String evalView = internalRenderer.evalView(request, response, model, locale, "index");

        logger.debug("evalView: " + evalView);

        //TODO: use the generated code to create the pdf and return it

    }

old response:

You could call /doSomething, getting back the generated html and pass it to another controller as a parameter to make it create the pdf and get it back as a final result (if it is strictly necessary generate the pdf from the html, maybe it's better to generate the pdf using the raw data)

call /doSomething (using ajax?)

get the generated html back

call /createPdf passing the generated html as a paramter

get the generated pdf back

Problem

How can I execute a JSP in controller and get html response in Sring variable without using `HtmlServletRequestWrapper` following is my code, i am trying to hit jsp get response html str and pass that html string to itext to generate pdf. ``` @RequestMapping(value = "/dosomething", method = RequestMethod.GET) public void dosomething(HttpServletRequest request, HttpServletResponse response) throws IOException { // setup your Cookie here response.setCookie(cookie) request.getRequestDispatcher("/WEB-INF/jsp/account_summary.jsp").include(request, response) } ```

Original source

Related problems