Back to Basics: Java 7 Feature – AutoCloseable interface – A tutorial/Overview

As an architect I always urge fellow developers to revisit and refresh their knowledge of java.lang, java.sql and java.util packages. It is time that I applied the rule on myself. So going forward I am going to look at interfaces/classes introduced since Java 5. Today’s blog post is going to cover the newly added Java 7 AutoCloseable interface.

During our day-to-day programming, we make use of number of resources which need to have their close method invoked on completion of their use in our code. The common example in I/O is java.io.FileInputStream or in JDBC is java.sql.Connection. These classes maintain a handle to the physical File or database connection which needs to be released as soon as its use is completed so that other processes can utilize the same. Java 7 has introduced the new interface AutoCloseable which defines a single close method. The interface implementations of AutoCloseable will in conjunction with the newly introduced try-with-resources statement provide a methodology to ensure that the resource is closed as soon as its operations are completed.

To understand this consider the following example. I created a class Resource1 which implements the AutoCloseable interface. The source code is shown below:

package com.java.autoclose;

public class Resource1 implements AutoCloseable {

	public Resource1() {	
	}
	
	@Override
	public void close() {
		System.out.println("Closing open resources in Resource 1.");
	}
}

In the close method implementation, I have written a single sysout statement.

To gain a better understanding of the functioning of the AutoCloseable interface in the context of try-with-resources statement, let’s create a test class Resource1Test. Source code of the class can be found below:

package com.java.autoclose.test;

import com.java.autoclose.Resource1;

public class Resource1Test {

	public static void main(String[] args) {
		try (Resource1 r = new Resource1()){
			System.out.println("Inside Resource 1 Test TRY block.");
		}
		System.out.println("Inside Resource 1 Test.");
	}
}

Refer the line number 8. In the try statement I have instantiated the Resource1 instance. This statement implies that the try-with-resources statement is used for Resource1.

Now run the class. The following output is generated:

Inside Resource 1 Test TRY block.
Closing open resources in Resource 1.
Inside Resource 1 Test.

The first line in the output implies that the code has entered the try statement. The next line implies that on completion of the try statement, the close method on the Resource1 instance was automatically invoked and on completion, the normal processing of the main method continued.

What happens if the try-with-resources block throws an exception?

Let’s create a test class Resource2Test. The test class Resource2Test is similar to Resource1Test. I have only added code to throw a RuntimeException(IllegalStateException).

package com.java.autoclose.test;

import com.java.autoclose.Resource1;

public class Resource2Test {

	public static void main(String[] args) {
		try (Resource1 r = new Resource1()){
			System.out.println("Inside Resource 2 Test TRY block.");
			throw new IllegalStateException();
		}
	}
}

The output of the Test class run is as follows:

Inside Resource 2 Test TRY block.
Closing open resources in Resource 1.
Exception in thread "main" java.lang.IllegalStateException
	at com.java.autoclose.test.Resource2Test.main(Resource2Test.java:10)

Although an exception was thrown, the resource was closed properly because of the presence of the try-with-resources statement block. To validate the behavior in case a checked exception is thrown, refer test class Resource3Test.

package com.java.autoclose.test;

import java.io.FileNotFoundException;

import com.java.autoclose.Resource1;

public class Resource3Test {

	public static void main(String[] args) throws FileNotFoundException {
		
		try (Resource1 r = new Resource1()){
			System.out.println("Inside Resource 3 Test TRY block.");
			throw new FileNotFoundException();
		}	
	}
}

The output of Resource3Test class run is as below:

Inside Resource 3 Test TRY block.
Closing open resources in Resource 1.
Exception in thread "main" java.io.FileNotFoundException
	at com.java.autoclose.test.Resource3Test.main(Resource3Test.java:13)

From the output it is clear that the behavior of the try-with-resources block remains unchanged.

The try-with-resources statement is not limited to creating an single implementation instance of AutoCloseable interface. Refer the source code of Resource2, Resource3 and Resource4Test class.

package com.java.autoclose;

public class Resource2 implements AutoCloseable {
	
	public Resource2() {
		
	}

	@Override
	public void close() {
		System.out.println("Closing open resources in Resource 2.");
		//throw new IllegalStateException();
	}
}
package com.java.autoclose;

public class Resource3 implements AutoCloseable {
	
	public Resource3() {
		
	}

	@Override
	public void close() {
		System.out.println("Closing open resources in Resource 3.");
		//throw new NullPointerException();
	}
}
package com.java.autoclose.test;


import com.java.autoclose.Resource1;
import com.java.autoclose.Resource2;
import com.java.autoclose.Resource3;

public class Resource4Test {

	public static void main(String[] args) {
		
		try (Resource1 r1 = new Resource1();
				Resource2 r2 = new Resource2();
				Resource3 r3 = new Resource3()){
			System.out.println("Inside Resource 4 Test TRY block.");
		} 
		System.out.println("Inside Resource 4 Test.");

	}
}

The try-with-resources statement in the class creates three AutoCloseable interface implementation instances Resource1, Resource2 and Resource3. Run the Resource4Test class. The following output is generated:

Inside Resource 4 Test TRY block.
Closing open resources in Resource 3.
Closing open resources in Resource 2.
Closing open resources in Resource 1.
Inside Resource 4 Test.

Clearly the close methods of the AutoCloseable interface implementations are invoked for all the 3 declared instances. Also pay attention to the fact that they are invoked in exactly the reverse order of their declaration in the try-with-resources statement.

The final piece to look at is exception handling. It is possible one or more than one AutoCloseable implementations can throw exception. We will have a single catch block to catch the exceptions. How do we get an handle to all the exceptions thrown?

Uncomment lines 12 in Resource2 and line number 12 in Resource3 classes respectively.

Look at the following Resource5Test class code.

package com.java.autoclose.test;

import com.java.autoclose.Resource1;
import com.java.autoclose.Resource2;
import com.java.autoclose.Resource3;

public class Resource5Test {

	public static void main(String[] args) {
		
		try (Resource1 r1 = new Resource1();
				Resource2 r2 = new Resource2();
				Resource3 r3 = new Resource3()){
			System.out.println("Inside Resource 5 Test TRY block.");
		} catch(Exception e) {
			System.out.println("Exception: " + e.getClass());
			Throwable[] t = e.getSuppressed();
			for (Throwable throwable : t) {
				System.out.println("Suppressed: ");
				throwable.printStackTrace();
			}
		}
		System.out.println("Inside Resource 5 Test.");
	}
}

We have written a single catch block. The exception caught has getSuppressed method to retrieve all the exceptions thrown during the individual close method invocations.

Refer the output on console below:

Inside Resource 5 Test TRY block.
Closing open resources in Resource 3.
Closing open resources in Resource 2.
Closing open resources in Resource 1.
Exception: class java.lang.NullPointerException
Suppressed: 
java.lang.IllegalStateException
	at com.java.autoclose.Resource2.close(Resource2.java:12)
	at com.java.autoclose.test.Resource5Test.main(Resource5Test.java:15)
Inside Resource 5 Test.

Note that the NullPointerException is thrown by Resource3 and IllegalStateException is thrown by Resource2. As per the try-with-resources statement practices, the last created resource is closed first and the first created resource is closed last.

That’s all for the moment.

Advertisements

4 thoughts on “Back to Basics: Java 7 Feature – AutoCloseable interface – A tutorial/Overview

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s