1

I am having trouble in returning compressed response (GZip) from my Java Servlet, to a JSP.

Flow :

  1. Request comes to java servlet
  2. Process the request, and create a JSON object, with the response
  3. Convert the JSON object to string
  4. Compress the response string with GZip
  5. The compressed response string is set as attribute in the request object and control passed to JSP
  6. In the JSP, the response string (compressed) is printed on screen

Precautions :

  1. Request object has "Accepting-Encoding" set with "gzip"
  2. Response header has "Content-Encoding" set to "gzip"
  3. Response content type is set to "application/json"
  4. Response character encoding is set to "ISO-8859-1"

Result :

  1. Firefox shows "Content Encoding Error"
  2. Chrome shows "Error 330 (net::ERR_CONTENT_DECODING_FAILED): Unknown error."

Can anyone help point me out, in the right direction please?

skaffman
  • 398,947
  • 96
  • 818
  • 769
Rohitesh
  • 967
  • 2
  • 14
  • 29

2 Answers2

4

The compressed response string is set as attribute in the request object and control passed to JSP

You shouldn't have forwarded a JSON response to a JSP. You should have printed the JSON plain to the response and have the JavaScript/Ajax code in your JSP Android app to call the URL of the servlet which returns the JSON. See also How to use Servlets and Ajax?.

As to the GZIP compression, you shouldn't do it yourself. Let the server do itself.

Fix your code to remove all manual attempts to compress the response, it should end up to basically look like this:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    String json = createItSomehow();
    response.setContentType("application/json");
    response.setCharacterEncoding("UTF-8");
    response.getWriter().write(json);
}

That's all, if you let your Android app call the URL of the servlet, it'll retrieve the JSON string.

Finally edit the server configuration to turn on automatic GZIP compression. In case of for example Tomcat, that would be a matter of adding compression="on" to the <Connector> element in Tomcat's /conf/server.xml file:

<Connector ... compression="on">

As per the documentation, the compressable mime types defaults to text/html,text/xml,text/plain. You can configure this to add application/json.

<Connector ... compression="on" compressableMimeType="text/html,text/xml,text/plain,application/json">

Unrelated to the concrete problem, the response character encoding must be set to UTF-8 which is as per the JSON specification.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you BalusC for the response. Actually, the reason I am doing it this way, is because I don't wish the JSP to consume this response. The response it to be consumed by an Android App, request this url. So, I have to print the response to a JSP, from where it is read by the http call made from the Android App. – Rohitesh Feb 24 '12 at 16:14
  • 1
    You should set it as a request attribute and **not** change the response headers. You're basically telling that the *entire* response is a JSON string which is Gzipped, but you're forwarding to a JSP which is in essence a `text/html` response and not Gzipped by the server. If you want to forward to a JSP to display the JSON string in a HTML response, then you should remove all code which changes the response headers and just set JSON string plain as request attribute the usual way. The compression has to be configured in server end. – BalusC Feb 24 '12 at 16:17
  • 2
    By the way, why don't you just let your Android app request the servlet URL directly instead of the JSP URL? How is it useful for the Android app to have a bunch of HTML around the JSON string? Just write the JSON immediately to the response as shown in the servlet examples in the "How to use Servlets and Ajax?" link. No need to forward to a JSP. – BalusC Feb 24 '12 at 16:22
  • I have asked a related question here http://stackoverflow.com/questions/11458234/how-will-an-android-client-if-tomcat7-server-has-gzip-compressed – Gaurav Agarwal Jul 12 '12 at 18:33
2

JSPs are for rendering textual data to the client. GZIP is binary data, even if it is compressed text underneath.

I suggest using a GZIP servlet filter to compress your data on the fly, instead of doing it programmatically in your business logic.

See this prior question for how to get hold of one off-the shelf: Which compression (is GZIP the most popular) servlet filter would you suggest?

Failing that, then write your own servlet filter that does the same thing.

Community
  • 1
  • 1
skaffman
  • 398,947
  • 96
  • 818
  • 769
  • Thank you Skaffman for the response. Actually, the reason I am doing it this way, is because I don't wish the JSP to consume this response. The response it to be consumed by an Android App, request this url. So, I have to print the response to a JSP, from where it is read by the http call made from the Android App. – Rohitesh Feb 24 '12 at 16:14
  • 2
    @user377349: Your servlet can output the JSON directly. It doesn't need a JSP. – skaffman Feb 24 '12 at 16:24