Some operating system and program resources such as file and database connections should have their connection closed by the programmer.  Whilst in general Java will try to handle this automatically during garbage collection (which could be hours later), putting close() operations inside a finally block guarantees that it happens immediately no matter if the code completed or threw an exception.

A finally block of code always gets called.  Guaranteed.  Finally is the recommended, safest and simplest way to close “resources” such as file handles and database connections.  Use finally!

In the following example, the method will work beautifully when there are no errors.  But if an SQLException is thrown execution will jump to the catch block and none of the close() calls will occur.  The JDBC driver will be one connection short.

public boolean isDocumentLocked(int documentId)  
       throws DataException
{
    boolean ret = true;
    try
    {
        Connection conn = getConnection();
        PreparedStatement ps = conn.prepareStatement(SQL_DOCUMENT_LOCKED);
        ps.setInt(1, documentId);
        ResultSet rs = ps.executeQuery();
        rs.next();
        ret = rs.getBoolean(1);
        rs.close();
        stmt.close();
        returnConnection(conn);
    }
    catch (SQLException e)
    {
        // Oops, the statement is never closed if there is an
        // exception.  The application will soon run out of
        // connections.
        throw new DataException("Could not check lock for "  
                                + documentId + ": ", e);
    }
    return ret;
}

The method would only be safe with a finally block, as below.

public boolean isDocumentLocked(int documentId)  
    throws DataException
{
    boolean ret = true;
    Connection conn = null;
    PreparedStatement ps = null;
    try
    {
        Connection conn = getConnection();
        ps = conn.prepareStatement(SQL_DOCUMENT_LOCKED);
        ps.setInt(1, documentId);
        ResultSet rs = stmt.executeQuery();
        rs.next();
        ret = rs.getBoolean(1);
    }
    catch (SQLException e)
    {
        throw new DataException("Could not check lock for "  
                               + documentId + ": ", e);
    }
    finally
    {
        if (ps != null) try {ps.close();} catch (SQLException e) {}
        if (rs != null) try {rs.close();} catch (SQLException e) {}
        if (conn != null) returnConnection(conn);
    }
    return ret;
}
            


blog comments powered by Disqus