1

My RSS servlet uses try-with-resource for the OutputStream out of the HttpServletResponse and the writer for it. In some cases SomeException is thrown whilst generating the RSS document, in which case I need to return an HTTP status 500 to the client:

try (ServletOutputStream out = response.getOutputStream();
     OutputStreamWriter writer = new OutputStreamWriter(out, "utf-8")) {
        response.setContentType("text/xml");

        // Generate RSS here

    } catch (SomeException e) {
        response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
        return;
    }

However, by the time response.sendError() is called, the $out$ has already been closed and I get said IllegalStateException saying that the response has already been committed (closing the stream seems to commit the response automatically ).

If I move the initialization of out and writer outside of the try-block and close them in a finally-block (the pre-Java7 way), the error code gets sent correctly.

I was wondering whether there's a way to keep using try-with-resource and still be able to return error codes in case of an exception.

Thanks!

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Keelhaul
  • 23
  • 5

1 Answers1

1

You don't need to close resources which you didn't create yourself. The container created the underlying OutputStream all by itself and is therefore also all by itself responsible for properly closing it. You should visualise it that the container has already put a try-with-resources around the servlet's doXxx() method. See also Should I close the servlet outputstream?

Differently put, the whole try-with-resources on OutputStream inside doXxx() is unnecessary.

Just do:

try {
    // Generate RSS here

    OutputStreamWriter writer = new OutputStreamWriter(response.getOutputStream(), "UTF-8")) {
    response.setContentType("text/xml");

    // Write RSS here.

} catch (SomeException e) {
    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}

Unrelated to the concrete problem, if you rethrow any checked exception as ServletException, then the container will also all by itself take care of the proper response code and message.

try {
    // ...
} catch (SomeException e) {
    throw new ServletException(e);
}
Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555