As I was cleaning up some code, FindBugs pointed me to a bit of JDBC code that uses Connection, CallableStatement, and ResultSet objects. Here's a snippet from that code:
CallableStatement cStmt = getConnection().prepareCall("...");
...
ResultSet rs = cStmt.executeQuery();
while ( rs.next() )
{
...
}
cStmt.close();
rs.close();
con.close();
FindBugs pointed out that these should be within a finally block. I started refactoring my code to do this and I started to wonder how to handle the code within the finally block.
It's possible that the creation of the CallableStatement of Connection objects would throw an exception, leaving my ResultSet object as null. When I try to close the ResultSet, I'd get a NullPointerException and my Connection would, in turn, never get closed. Indeed, this thread brings up the same concept and shows that wrapping your close() invocations in a null check is a good idea.
But what about other possible exceptions? According to the Java API spec, Statement.close() can throw a SQLException "if a database error occurs". So, even if my CallableStatement is not null and I can successfully call close() on it, I might still get an exception and not have a chance to close my other resources.
The only "fail safe" solution I can think of is to wrap each close() invocation in its own try/catch block, like this:
finally {
try {
cStmt.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
try {
rs.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
try {
con.close();
} catch (Exception e) { /* Intentionally Swallow Exception */ }
}
Boy, if that doesn't look awful. Is there a better way to go about this?
I think the best answer has already being mentioned, but I thought it could be interesing to mention that you could consider the new JDK 7 feature of autoclosable resources.
try{
try(Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/hrdb", "obiwan", "kenobi");
Statement stm = conn.createStatement();
ResultSet rs = stm.executeQuery("select name from department")) {
while(rs.next()){
System.out.println(rs.getString("name"));
}
}
}catch(SQLException e){
//you might wanna check e.getSuppressed() as well
//log, wrap, rethrow as desired.
}
Not all of us can migrate to JDK 7 now, but for those who can start playing with the developer preview, this offer an interesting way of doing things and certainly may deprecate other approaches in the near future.
Use Lombok's cleanup, if you can:
#Cleanup
Connection c = ...
#Cleanup
statement = c.prepareStatement(...);
#Cleanup
rs = statement.execute(...);
This works translates to three nested try-finally blocks and works fine with exception. Never ever swallow an exception without a very good reason!
An alternative:
Write an own utility method like this:
public static void close(ResultSet rs, Statement stmt, Connection con) throws SQLException {
try {
try {
if (rs!=null) rs.close();
} finally {
if (stmt!=null) stmt.close();
}
} finally {
if (con!=null) con.close();
}
}
and use it in
try {
Connection con = ...
Statement stmt = ...
ResultSet rs = ...
} finally {
close(rs, stmt, con);
}
and let the Exception bubble up or handle it as you want.
Well basically that is what you do except you first of all don't necessarily swallow the exception (you can null check and at least LOG the exception). Second, you can set up a nice utility class with things like
public static void close(ResultSet rs) {
try { if (rs != null) rs.close();
} catch (SQLException (e) {
log.error("",e);
}
}
Then you just static import that class.
your finally becomes something like
finally {
close(resultset);
close(statement);
close(connection);
}
which really isn't that hideous.
You only have to close the Connection.
try
{
cStmt.close();
}
catch(Exception e)
{
/* Intentionally Swallow Exception */
}
From docs.oracle.com:
A Statement object is automatically closed when it is garbage collected. When a Statement object is closed, its current ResultSet object, if one exists, is also closed.
Calling close() on a Connection releases its database and JDBC resources.
The only way I know to hide all that ugly try-catch boilerplate code is to utilize something like Spring's JBDC Template.
You can wrap one block into another block:
try{
Connection c = ...
try{
statement = c.prepareStatement(...);
try{
rs = statement.execute(...);
}finally{
rs.close();
}
}finally{
statement.close()
}
}finally{
c.close();
}
}catch(SQLException e){}
Use the lowermost catch-block for everything that might crop up
Related
Consider the code:
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.createStatement(myQueryString);
rs = ps.executeQuery();
// process the results...
} catch (java.sql.SQLException e) {
log.error("an error!", e);
throw new MyAppException("I'm sorry. Your query did not work.");
} finally {
ps.close();
rs.close();
}
The above does not compile, because both PreparedStatement.close() and ResultSet.close() throw a java.sql.SQLException. So do I add a try/catch block to the finally clause? Or move the close statements into the try clause? Or just not bother calling close?
In Java 7, you should not close them explicitly, but use automatic resource management to ensure that resources are closed and exceptions are handled appropriately. Exception handling works like this:
Exception in try | Exception in close | Result
-----------------+--------------------+----------------------------------------
No | No | Continue normally
No | Yes | Throw the close() exception
Yes | No | Throw the exception from try block
Yes | Yes | Add close() exception to main exception
| | as "suppressed", throw main exception
Hopefully that makes sense. In allows pretty code, like this:
private void doEverythingInOneSillyMethod(String key)
throws MyAppException
{
try (Connection db = ds.getConnection()) {
db.setReadOnly(true);
...
try (PreparedStatement ps = db.prepareStatement(...)) {
ps.setString(1, key);
...
try (ResultSet rs = ps.executeQuery()) {
...
}
}
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
Prior to Java 7, it's best to use nested finally blocks, rather than testing references for null.
The example I'll show might look ugly with the deep nesting, but in practice, well-designed code probably isn't going to create a connection, statement, and results all in the same method; often, each level of nesting involves passing a resource to another method, which uses it as a factory for another resource. With this approach, exceptions from a close() will mask an exception from inside the try block. That can be overcome, but it results in even more messy code, and requires a custom exception class that provides the "suppressed" exception chaining present in Java 7.
Connection db = ds.getConnection();
try {
PreparedStatement ps = ...;
try {
ResultSet rs = ...
try {
...
}
finally {
rs.close();
}
}
finally {
ps.close();
}
}
finally {
db.close();
}
If you're really hand-rolling your own jdbc it definitely gets messy. The close() in the finally needs to get wrapped with its own try catch, which, at the very least, is ugly. You can't skip the close, although the resources will get cleared when the connection is closed (which might not be right away, if you're using a pool). Actually, one of the main selling points of using a framework (e.g. hibernate) to manage your db access is to manage the connection and result set handling so you don't forget to close.
You can do something simple like this, which at least hides the mess, and guarantees that you don't forget something.
public static void close(ResultSet rs, Statement ps, Connection conn)
{
if (rs!=null)
{
try
{
rs.close();
}
catch(SQLException e)
{
logger.error("The result set cannot be closed.", e);
}
}
if (ps != null)
{
try
{
ps.close();
} catch (SQLException e)
{
logger.error("The statement cannot be closed.", e);
}
}
if (conn != null)
{
try
{
conn.close();
} catch (SQLException e)
{
logger.error("The data source connection cannot be closed.", e);
}
}
}
and then,
finally {
close(rs, ps, null);
}
For file I/O, I generally add a try/catch to the finally block. However, you must be careful not to throw any exceptions from the finally block, since they will cause the original exception (if any) to be lost.
See this article for a more specific example of database connection closing.
Don't waste your time coding low-level exception management, use an higher-level API like Spring-JDBC, or a custom wrapper around connection/statement/rs objects, to hide the messy try-catch ridden code.
Also note:
"When a Statement object is closed, its current ResultSet object, if one exists, is also closed. "
http://java.sun.com/j2se/1.5.0/docs/api/java/sql/Statement.html#close()
It should be sufficient to close only the PreparedStatement in a finally, and only if it is not already closed. If you want to be really particular though, close the ResultSet FIRST, not after closing the PreparedStatement (closing it after, like some of the examples here, should actually guarantee an exception, since it is already closed).
I usually have a utility method which can close things like this, including taking care not to try to do anything with a null reference.
Usually if close() throws an exception I don't actually care, so I just log the exception and swallow it - but another alternative would be to convert it into a RuntimeException. Either way, I recommend doing it in a utility method which is easy to call, as you may well need to do this in many places.
Note that your current solution won't close the ResultSet if closing the PreparedStatement fails - it's better to use nested finally blocks.
Building on #erickson's answer, why not just do it in one try block like this?
private void doEverythingInOneSillyMethod(String key) throws MyAppException
{
try (Connection db = ds.getConnection();
PreparedStatement ps = db.prepareStatement(...)) {
db.setReadOnly(true);
ps.setString(1, key);
ResultSet rs = ps.executeQuery()
...
} catch (SQLException ex) {
throw new MyAppException("Query failed.", ex);
}
}
Note that you don't need to create the ResultSet object inside the try block as ResultSet's are automatically closed when the PreparedStatement object is closed.
A ResultSet object is automatically closed when the Statement object
that generated it is closed, re-executed, or used to retrieve the next
result from a sequence of multiple results.
Reference: https://docs.oracle.com/javase/7/docs/api/java/sql/ResultSet.html
If your are using Java 7 you can use the improvements in the exception handling mechanisms in those classes that implement AutoCloseable (i.e. PreparedStatement, Resultset)
You might also find this question interesting: Closing ResultSet in Java 7
I know this is an old question, but just in case someone is looking for the answer, java now has the try-with-resouce solution.
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
Do no omit calling close. It may cause problems.
I prefer adding try/catch block to the finally.
focus finally clause,
finally {
try {
rs.close();
ps.close();
} catch (Exception e) {
// Do something
}
}
I think you have to modify 2 points.
First, use try & catch again in fainlly clause.
Second, do rs.close() before doing ps.close().
fly1997#naver.com
Probably an old (though simple) way to do things, but it still works:
public class DatabaseTest {
private Connection conn;
private Statement st;
private ResultSet rs;
private PreparedStatement ps;
public DatabaseTest() {
// if needed
}
public String getSomethingFromDatabase(...) {
String something = null;
// code here
try {
// code here
} catch(SQLException se) {
se.printStackTrace();
} finally { // will always execute even after a return statement
closeDatabaseResources();
}
return something;
}
private void closeDatabaseResources() {
try {
if(conn != null) {
System.out.println("conn closed");
conn.close();
}
if(st != null) {
System.out.println("st closed");
st.close();
}
if(rs != null) {
System.out.println("rs closed");
rs.close();
}
if(ps != null) {
System.out.println("ps closed");
ps.close();
}
} catch(SQLException se) {
se.printStackTrace();
}
}
}
I use this..
finally
{
if (ps != null) ps.close();
if (rs != null) rs.close();
}
I'm writing a transaction with Java 8. First, my code was like this.
try (Connection conn = DAOUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(addSubscriptionSql)) {
conn.setAutoCommit(false);
//do work
conn.commit();
} catch (SQLException e) {
e.printStackTrace(); //handle error
}
But since I should rollback in case of transaction failure, I had to change the code like this. Note the two try blocks.
try (Connection conn = DAOUtil.getConnection()) {
try (PreparedStatement ps = conn.prepareStatement(addSubscriptionSql)) {
conn.setAutoCommit(false);
//do work
conn.commit();
} catch (SQLException e) {
conn.rollback();
e.printStackTrace(); //handle error
}
} catch (SQLException e) {
e.printStackTrace(); //handle error
}
My question is, is there a better (I mean simpler) way of doing this? Can I achieve this with a single try block?
You can use
try(Connection conn = DAOUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(addSubscriptionSql);
AutoCloseable finish = conn::rollback) {
conn.setAutoCommit(false);
//do work
conn.commit();
}
This will always call rollback(), but after a successful completion of commit(), the rollback will become a no-op as it resets the state to that after the last successful completion of commit()…
Since AutoCloseable declares to throw Exception that will require to handle this broad exception type. It can be fixed with a custom type that might be useful in other cases as well:
interface SQLCloseable extends AutoCloseable {
#Override public void close() throws SQLException;
}
…
try(Connection conn = DAOUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(addSubscriptionSql);
SQLCloseable finish = conn::rollback) {
conn.setAutoCommit(false);
//do work
conn.commit();
}
Now, only the handling of the exception type SQLException is enforced.
If you don’t like the idea of rollback() being called unconditionally, the solution becomes less elegant:
boolean[] success = { false };
try(Connection conn = DAOUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(addSubscriptionSql);
SQLCloseable finish = () -> { if(!success[0]) conn.rollback(); }) {
conn.setAutoCommit(false);
//do work
conn.commit();
success[0] = true;
}
If you reset the auto-commit state at the end, you could use that as an indicator for the necessity of a roll-back:
try(Connection conn = DAOUtil.getConnection();
PreparedStatement ps = conn.prepareStatement(addSubscriptionSql);
SQLCloseable finish = () -> { if(!conn.getAutoCommit()) conn.rollback(); }) {
conn.setAutoCommit(false);
//do work
conn.commit();
conn.setAutoCommit(true);
}
Can I achieve this with a single try block?
No, because your conn object will not be available in the catch block of your try-with-resources. If you want to catch an exception while executing the PreparedStatement and explicitly do a conn.rollback() then the rollback will have to happen within the try of the try-with-resources that creates the conn object (i.e., using a second nested try block for the PreparedStatement call).
I have connection provider class as bleow to return connection.
public class ConnectionProvider {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection ConnectDB() throws ClassNotFoundException, SQLException {
try (Connection connection = DriverManager
.getConnection("jdbc:mysql://localhost:3306/jspservlet_test","root", "root");
) {
return connection;
}
}
}
Here is main method to call connection provider.
public void Test() {
try {
Connection con = ConnectionProvider.ConnectDB();
PreparedStatement ps = con.prepareStatement("");
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
But "com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed." error are always show at below line of code.
PreparedStatement ps = con.prepareStatement("");
Because, according to Oracle documentation, If use try with resources java 7 features, resources are auto close after try block even it's errors occurred or not. So even I returned the connection it's already closed.
Let me know, my usage logic is wrong?
How can I return this connection inside try with resource?
I tried many time googling for solution but does not get convenience answers for me.
Let me know your suggestion and feedback please.
What you can't do...
With a try-with-resources as you have it after you return the connection you return(d) is close(d). You can't return the connection from inside the try with resources.
What you can do...
Pass the connection (inside your try-with-resources) to a method that takes a connection. You can also use a ConnectionPool, and get the Connection when you need it (to create and execute a query).
Let me know, my usage logic is wrong?
The usage of 'try-with-resources' logic is wrong in this context, because the intention of ConnectDB() is to return a connection instance which could be actually used by the caller to send a SQL statement, but instead, the connection instance is getting auto-closed, before it could be used by the caller, because of using 'try-with-resources' construct of Java.
Quick how-to on try-with-resource and JDBC
Your ConnectionProvider's ConnectDB already declares it is throwing SQLException - so no need to catch it in here: (You should consider replacing this code with connection pool maybe)
public class ConnectionProvider {
static {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
public static Connection ConnectDB() throws SQLException {
return DriverManager.getConnection("jdbc:mysql://localhost:3306/jspservlet_test","root", "root");
}
}
Instead use try-with-resource in your test-class to clean up your code and focus on errors your SQL code
might have:
public void Test() {
try (Connection con = ConnectionProvider.ConnectDB();
PreparedStatement ps = con.prepareStatement("SELECT 1")) {
//Prepare your Statement
ps.setInt(1, 1);
//And another try-with-resource for the result - note the closing brace
try(ResultSet rs = ps.executeQuery()) {
while(rs.next()) {
//Handle your Result
System.out.println(rs.getString(1));
}
} // This closes try-with-resource. Exception will be rethron to be caught in outer catch!
} catch (SQLException e) {
//SQL is Broken - but only ONE catch to catch them all
e.printStackTrace();
}
}
That way you gain
Better readability for your code (no calls to close surrounded by finally and if != null)
Centralized error handling if anything in your SQL code breaks (so you can focus on functional error of "statement didn't run")
Better code quality: No need to worry about Cursors, Statements, Connections not being propery closed.
I am stuck with this problem here. I am running an application on my Tomcat Application Server. As a frontend I am using an HTML site with javascript in it, in the backend i am using Java.
When the user clicks on a button several sql queries are made, one after another. Now I want to provide the ability to cancel this query if the user wants to.
I already checked if my jdbc driver and the database are compatible for the cancel() method and this is just fine.
Here is my code :
PreparedStatement stmt = null;
public void runQuery(String query) {
Connection con = getConnection();
try {
stmt = con.prepareStatement(query);
stmt.execute();
} catch(SQLException e) {
e.printStackTrace();
} finally {
if(stmt != null && !stmt.isClosed()) {
stmt.close();
}
if(con != null) {
con.close();
}
}
}
public void cancelQuery() {
try {
if(stmt != null && !stmt.isClosed()) {
stmt.cancel();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
So the user clicks the run button => runQuery is executed and stmt is initialized/overriden with the query which needs to execute.
Then the user clicks the cancel button => cancelQuery is executed.
Unfortunately I sometimes get a NullPointerException because stmt is null. But it should not even call cancelQuery if the stmt is null ?!
Here is the stacktrace:
Stacktrace:] with root cause
java.lang.NullPointerException
at com.sybase.jdbc3.jdbc.SybStatement.doCancel(SybStatement.java:646)
at com.sybase.jdbc3.jdbc.SybStatement.cancel(SybStatement.java:614)
at org.apache.tomcat.dbcp.dbcp2.DelegatingStatement.cancel(DelegatingStatement.java:269)
at org.apache.tomcat.dbcp.dbcp2.DelegatingStatement.cancel(DelegatingStatement.java:269)
at de.package.util.DBHelper.cancelQuery(DBHelper.java:82)
.....
Any idea why this keeps producing an exception ? How can I cancel the statement the right way ?
EDIT:
I had allook at the link in the comments and now running the cancel() method from a different thread. However the NullPointer still happens. This is how i call the cancel() method now:
public void cancelQuery() {
Thread thread = new Thread(new SQLCancelRunnable(stmt));
thread.start();
}
public class SQLCancelRunnable implements Runnable {
PreparedStatement stmt;
public SQLCancelRunnable(PreparedStatement stmt) {
this.stmt = stmt;
}
#Override
public void run() {
if(stmt != null) {
try {
System.out.println(stmt);
System.out.println(stmt.toString());
stmt.cancel();
System.out.println("canceled");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
EDIT2
Found my answer the problem was the finally block of the runQuery() method. Because I closed statement & connection the NullPointer was thrown.
I now removed this block but this, of course, leads to huge resource leaking. Anyone who can guide me in the right direction how to close my resources properly ?
PreparedStatement stmt = null;
public void runQuery(String query) {
Connection con = getConnection();
try {
stmt = con.prepareStatement(query);
stmt.execute();
}
catch(SQLException e) {
e.printStackTrace();
}
finally {
if(stmt != null && !stmt.isClosed()) {
stmt.close();
}
if(con != null) {
con.close();
}
}
}
public void cancelQuery() {
try {
if(stmt != null && !stmt.isClosed()) {
stmt.cancel();
}
} catch (SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
Try this. I have added a Generic Exception just after the SQLException.
Cannot say this is a very clean solution but it will ignore the null pointer exception which is possiblly raised by stmt.close() statement.
You'll need to synchronize statement closing:
public void runQuery(String query) {
...
try {
stmt = con.prepareStatement(query);
stmt.execute();
...
finally {
synchronized(this) {
if(stmt != null && !stmt.isClosed()) {
stmt.close();
}
}
}
}
public void cancelQuery() {
synchronized(this) {
if(stmt != null && !stmt.isClosed()) {
stmt.cancel();
}
}
}
between every statement another thread may execute some kind of code, so a simple if is not sufficient to be sure the state of the world is as you expect it to be.
Synchronizing on this may not be the best option, but as the stmt may be null we can't use this object.
Edit: If the code starting the query is asynchronous you'll also have to be prepared for calls to cancelQuery even before your statement is prepared.
You can use Statement.cancel()
As Java Docs Says
void cancel()
throws SQLException
Cancels this Statement object if both the DBMS and driver support
aborting an SQL statement. This method can be used by one thread to
cancel a statement that is being executed by another thread.
You can also set setQueryTimeout if query execution passes a threshhold time
java.sql.Statement.setQueryTimeout(seconds)
Update
Don't forget to Rollback the transation
Anyone who can guide me in the right direction how to close my
resources properly ?
this is what for finally block was invented
finally{
//Release All Resources
}
The finally block always executes when the try block exits. This
ensures that the finally block is executed even if an unexpected
exception occurs. But finally is useful for more than just exception
handling — it allows the programmer to avoid having cleanup code
accidentally bypassed by a return, continue, or break. Putting cleanup
code in a finally block is always a good practice, even when no
exceptions are anticipated.
You should take a look at Apache DB-Utils it makes this kind of problems disappear and you can simply write something like:
} finally {
DbUtils.closeQuietly(resutlSet);
DbUtils.closeQuietly(preparedStatement);
DbUtils.closeQuietly(connection);
}
Is there anything wrong with using a parent function to handle all the messy catch/finally stuff in a connection pool?
public Connection getConnection() {
try {
return this.dataSource.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public ResultSet executeQuery(Connection connection, PreparedStatement stmt) {
try {
return stmt.executeQuery();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
return null;
}
No problem except the fact that you are eating the exceptions and not throwing them.Throwing an exception is a better idea to allow the calling methods to take appropriate actions.
Note: if you can move to Java 7 and use try with resource then you will save a lot of such mess. Learn more about it here: http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
This is an example of the Facade Pattern.
There's nothing wrong with it, except your should make those methods static, so they are (stateless) utility methods.
You'll have much cleaner code if you use the try-with-resources pattern and focus on minimizing the scope of your resources. In particular, you problematically open resources (the connection and the statement) separately from the close behavior. By splitting it up, you make it easy to make mistakes, or create inefficient code. For example, perhaps you should not close the connection after executing the query.
Instead, you should generally open and close resources in the same place, and anywhere you pass around these resources you trust (create an invariant) that they are and will remain open. This cleanly compartmentalizes the obtaining-resources behavior from the using-resources behavior, and lets you clearly limit the scope these resources are open for.
Compare your code:
Connection conn = getConnection();
PreparedStatement ps = ...; // construct PreparedStatement
ResultSet rs = executeQuery(conn, ps);
// use ResultSet
/* now secretly your Connection and PreparedStatement are closed (even if you wanted
to use them again) though your result set is still open and needs to be closed.
Admittedly it's concise, but what's actually going on is very unclear. */
To my code:
public static void main(String[] args) {
try(Connection conn = this.dataSource.getConnection()) {
// All calls in this block, and only calls in this block, can use the connection
buildObjectWithDBData(conn); // method does exactly what the name implies
// do more calls against our connection as needed
}
}
public static void buildObjectWithDBData(Connection conn) {
try(PreparedStatement ps = /* generate prepared statement */;
ResultSet rs = ps.executeQuery()) {
// do work with result set, populate the data we need
}
// at this point we know the connection is alive in a clean, stable state,
// the resources opened here are closed, and we've done the work we need
}
I'll grant, mine is a little more verbose. But it's much more clear what it's doing, and at every step in the process we explicitly limit the scope of our objects and resources to as little as possible, rather than relying on side-effects of arbitrary method calls to secretly close objects and leave them still in scope, but unusable.