Java 7’s Automatic Resource Management now covers JDBC
Nov 15
Java 7 ARM, Java, Java7, JDK7, OpenJDK, Project Coin 6 Comments
One of the most eye-catching new features of Java 7’s Project Coin (JSR Pending) is Automatic Resource Management (ARM). ARM removes the need to write exception handling and resource management code for I/O streams, socket connections and other resources. In other words, there will no longer be a need to write error-prone try/catch statements, nor tedious resource cleanup code.
As stated on Joseph D. Darcy’s Oracle Weblog, ARM support is to be added to JDBC, which will provide much relief to ORM providers and day to developers alike!
This blog entry will highlight the benefits of ARM via a basic I/O based code example and will then go one to show a similar example for JDBC.
Lets imagine you’ve been asked to read a file containing the names of the New Zealand Football squad, and print those names out line by line. The existing (JDK 6) way of writing this code would probably look a little something like this:
FileReader fr;
BufferedReader br;
try
{
String teamMember;
fr = new FileReader('/home/NZTeamList.txt');
br = new BufferedReader(fr);
while ((teamMember = br.readLine()) != null)
{
System.out.println(teamMember);
}
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (br!= null)
{
br.close();
if (fr != null)
{
fr.close();
}
}
}
As well as making sure that you cleanly close of the BufferedReader and the FileReader, notice all of the extra try/catch exception handling you have to put in place. It would be all to easy to miss a close() call or to declare a catch incorrectly.
Now lets look at the same problem with ARM involved. ARM removes the need for the explicit exception handling and automatically closes off resources for you:
String teamMember = null;
try (BufferedReader br =
new BufferedReader(new FileReader('/home/NZTeamList.txt')))
{
while ((teamMember = br.readLine()) != null)
{
System.out.println(teamMember);
}
}
Notice the new syntax – the resources which will be managed are now inside a try()
parenthesis and the exception handling (i.e. the ‘catch’ blocks) is gone. The logic is now much cleaner and focused purely on the task at hand, no extra code for resource management is required.
You might be asking yourself: “Does that work for any manageable resource in the Java Standard Edition?” and the answer would be “No…. for now”. But a large step in the right direction has been made with the announcement that JDBC would be getting ARM support. JDBC is an area where most of the code that you write tends to focus more on exception handling and resource management than the actual business logic, so ARM can be put to good use here.
Lets say you have to retrieve and print out some employee salaries from a mySQL database. To refresh your memory, here’s an example of the current way of establishing a connection to a MySQL database using ye olde Connection, Statement and ResultSet interfaces:
String connectionURL = 'jdbc:mysql://localhost:3306/myDB';
Connection connection = null;
Statement st = null;
ResultSet rs = null;
try
{
Class.forName('com.mysql.jdbc.Driver').newInstance();
connection = DriverManager.getConnection(connectionURL, 'root', 'admin');
st = connection.createStatement();
rs = st.executeQuery('Select * from EMPLOYEE_SALARIES');
while (rs.next())
{
System.out.println('EMPLOYEE_NAME/EMPLOYEE_SALARY');
System.out.println(rs.getString(1) + '/' + rs.getString(2));
}
}
catch (ClassNotFoundException ex)
{
ex.printStackTrace();
}
catch (SQLException ex)
{
ex.printStackTrace();
}
catch (InstantiationException ex)
{
ex.printStackTrace();
}
catch (IllegalAccessException ex)
{
ex.printStackTrace();
}
finally
{
try
{
if (rs != null && !rs.isClosed())
{
rs.close();
}
if (st != null && !st.isClosed())
{
st.close();
}
if (connection != null && !connection.isClosed())
{
connection.close();
}
}
catch (SQLException ex)
{
ex.printStackTrace();
}
}
What is wrong with the above code? Compiler-wise…. nothing. But the abundance of exception-handling code simply overwhelms the core executeQuery()/parsing of the result set business logic.
If we look back to the ARM version of the first example, applying that paradigm to the JDBC code example above, should result in a cleaner version. More specifically there will be no ’catch’ clauses and no code to close the opened connections, statements and result sets. An approximate version might look something like the following:
String connectionURL = 'jdbc:mysql://localhost:3306/myDB';
try
(
Connection connection =
DriverManager.getConnection(connectionURL, 'root', 'admin');
Statement st = connection.createStatement();
ResultSet rs = st.executeQuery('Select * from EMPLOYEE_SALARIES');
)
{
Class.forName('com.mysql.jdbc.Driver').newInstance();
while (rs.next())
{
System.out.println('EMPLOYEE_NAME/EMPLOYEE_SALARY');
System.out.println(rs.getString(1) + '/' + rs.getString(2));
}
}
The differences between ‘without ARM’ and ‘with ARM’ cases is indeed considerable. With ARM, the developer’s focus remains on the business logic.
Nevertheless, using ARM for automatically closing previously-opened resources raises some concerns. The most obvious of these is how the closing of the Connection will affect transactional behaviour. Should all transactions be committed or rolled back before ARM calls “close()” on the Connection? If the runtime resource manager decides to close the connection suddenly and not all changes have been committed, what would be the consequences of automatically rolling back everything? These questions are more will be answered in a follow up post once we get our hands on the first ARM/JDBC supported build.
Cheers,
Martijn, Ben and Dragos (our fantastic intern!).
RSS
Twitter
Email
Facebook
Join our Early Access Program, read chapters now!
Nov 15, 2010 @ 23:04:23
There are some syntax/functional errors in previous code snippets:
1. snippet )
- FileReader & BufferedReader must be defined before try block because there will not be seen in the finally block.
- closing() must be called in another try/catch clause
2. snippet )
- all SQL resources in finally block first must be compared to null because of possible NullPointerException
Nov 20, 2010 @ 17:42:40
Looking forward to ARM feature
Feb 10, 2011 @ 15:19:04
Hi Martin, right you are, thanks for spotting that! We’ve updated the code samples and hopefully got the formatting a little nicer as well
Mar 15, 2012 @ 09:57:31
Interesting idea and surely useful. However, automatic resource cleanup has been made available for the Java platform by the Spring framework using the template approach (e.g. JdbcTemplate, JmsTemplate, HibernateTemplate etc.).
That approach decreases the amount of boiler plate code even further and lets the programmer focus on the essential logic. ARM just addresses the resource cleanup.