views:

34

answers:

1

Hi,

I am currently developing a REST web service with Jersey / Tomcat (but a generic Servlet/Container answer is welcome). If the client does some GET requests on services that return large amount of data, from a MySQL connection.

To avoid any OOM exception, I use a streaming mode for MySQL.

However, if the client aborts the request during the load, then the MySQL connection is not closed. After that, the server won't process any other request, as only one "streaming" request is possible at a time.

So the question is : How can I be notified whenever a request ends on my server (normally or abnormally). Can I register some kind of listener ? Or use a UncaughtExceptionHandler ?

I have seen many things about handling exceptions in Jersey to transform them into "Response", but nothing to handle the prematurely end of a request. I guess Jersey or Tomcat might simply destroy my thread without notification. Can I catch some exception in critical parts of my methods to know whenever such Thread interruption happens ?

Thanks in advance for your help,

Raphael

+1  A: 

Usually, an IOException will be thrown whenever flush() or close() has been called on the response.getOutputStream() while the other side has aborted the connection.

Usually, closing the DB connection (and other resources) should happen in the finally block of the try block where it is been opened, so that it will be closed anyway in case of exceptions.

Summarized, this example should do:

String search = getItSomehow();
Connection connection = null;
PreparedStatement statement = null;
ResultSet resultSet = null;

try {
    connection = database.getConnection();
    statement = connection.prepareStatement(SQL_FIND);
    statement.setString(1, search);
    resultSet = statement.executeQuery();

    if (resultSet.next()) {
        response.setContentType(resultSet.getString("contentType"));
        response.setContentLength(resultSet.getInt("contentLength")); // Optional.
        BufferedInputStream input = null;
        BufferedOutputStream output = null;
        try {
            input = new BufferedInputStream(resultSet.getBinaryStream("content"));
            output = new BufferedOutputStream(response.getOutputStream());
            byte[] buffer = new byte[1024];
            for (int length; (length = input.read(buffer)) > 0;) {
                output.write(buffer, 0, length);
                output.flush;
            }
        } finally {
            if (output != null) try { output.close(); } catch (IOException logOrIgnore) {}
            if (input != null) try { input.close(); } catch (IOException logOrIgnore) {}
        }
    } else {
        response.sendError(HttpServletResponse.SC_NOT_FOUND);
    }
} catch (SQLException e) {
    throw new ServletException("Something failed at SQL/DB level.", e);
} finally {
    if (resultSet != null) try { resultSet.close(); } catch (SQLException logOrIgnore) {}
    if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
    if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
BalusC