HttpServletResponse#sendError How to change ContentType

pdegand59 picture pdegand59 · Jan 22, 2013 · Viewed 17.2k times · Source

I'm creating a simple Servlet to answer a form submition. This servlet receive POST request and should response Application/JSON datas. This is working well. I want now to add errors managment to my servlet: If the servlet receive bad request parameters, I want it to answer the client a 400 — "Bad Request" response with a simple {"error":"ERROR MESSAGE"} JSON response.

I'm using the HttpServletResponse#sendError(int,String) to correctly send the error but the ContentType of the response is always set to text/html, even though I used HttpServletResponse#setContentType("application/json") before.

Is this the good way to send error using Servets ? How can I force the ContentType of the response to application/json?

Sample code of the doPost() method of my test Servlet :

public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("application/json;charset=UTF-8");
        PrintWriter out = response.getWriter();
        out.print("{\"error\":1}");
        response.sendError(HttpServletResponse.SC_BAD_REQUEST);
}

Answer

Jason Winnebeck picture Jason Winnebeck · Sep 26, 2014

I recently had this issue when wanting to send error messages inside of a JAX-RS application. sendError would always return text/html, per the spec. I had to do the following, given a HttpServletResponse response:

response.resetBuffer();
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.setHeader("Content-Type", "application/json");
response.getOutputStream().print("{\"errorMessage\":\"You can't use this!\"}");
response.flushBuffer(); // marks response as committed -- if we don't do this the request will go through normally!

The flushBuffer is critical to mark the response as committed, as sendError does. At first I tried just calling close on the output stream, but what would happen is my filter would run then the JAX-RS resource would continue to run normally, then I'd get the error message AND the normal response concatenated together with 200 status code!

resetBuffer is there just in case anything else has set headers or written some content before this filter.