automatically closing a resource passed as an argument - java

If I want to automatically close a resource passed as an argument, is there a more elegant solution than this?
void doSomething(OutputStream out) {
try (OutputStream closeable = out) {
// do something with the OutputStream
}
}
Ideally, I'd like to have this resource closed automatically, without declaring another variable closeable that refers to the same object as out.
Aside
I realise that closing out within doSomething is considered a bad practice

With Java 9 and higher, you can do
void doSomething(OutputStream out) {
try (out) {
// do something with the OutputStream
}
}
This is only allowed if out is final or effectively final. See also the Java Language Specification version 10 14.20.3. try-with-resources.

I use Java 8 and it does not support Resource Reference. What about create universal method that accepts Closable and payload:
public static <T extends Closeable> void doAndClose(T out, Consumer<T> payload) throws Exception {
try {
payload.accept(out);
} finally {
out.close();
}
}
Client code could look like this:
OutputStream out = null;
doAndClose(out, os -> {
// do something with the OutputStream
});
InputStream in = null;
doAndClose(in, is -> {
// do something with the InputStream
});

void doSomething(OutputStream out) {
try {
// do something with the OutputStream
}
finally {
org.apache.commons.io.IOUtils.closeQuietly(out);
}
}

Related

Reduce nesting when cleaning up multiple non-Closeable resources

I have a Closeable that needs to clean up multiple resources in the close() method. Each resource is a final class that I cannot modify. None of the included resources are Closeable or AutoCloseable. I also need to call super.close(). So it appears that I cannot handle any of the resources* using try-with-resources. My current implementation looks something like this:
public void close() throws IOException {
try {
super.close();
} finally {
try {
container.shutdown();
} catch (final ShutdownException e) {
throw new IOException("ShutdownException: ", e);
} finally {
try {
client.closeConnection();
} catch (final ConnectionException e) {
throw new IOException("Handling ConnectionException: ", e);
}
}
}
}
I'd prefer a solution with less crazy nesting but I can't figure out how to take advantage of try-with-resources or any other features to do that. Code sandwiches don't seem to help here since I'm not using the resources at all, just cleaning them up. Since the resources aren't Closeable, it's unclear how I could use the recommended solutions in Java io ugly try-finally block.
* Even though the super class is Closeable, I cannot use super in a try-with-resources because super is just syntactic sugar and not a real Java Object.
This a good (albeit unorthodox) case for try-with-resources. First, you'll need to create some interfaces:
interface ContainerCleanup extends AutoCloseable {
#Override
void close() throws ShutdownException;
}
interface ClientCleanup extends AutoCloseable {
#Override
void close() throws ConnectionException;
}
If these interfaces are only used in the current class, I'd recommend making them inner interfaces. But they also work as public utility interfaces if you use them in multiple classes.
Then in your close() method you can do:
public void close() throws IOException {
final Closeable ioCleanup = new Closeable() {
#Override
public void close() throws IOException {
YourCloseable.super.close();
}
};
final ContainerCleanup containerCleanup = new ContainerCleanup() {
#Override
public void close() throws ShutdownException {
container.shutdown();
}
};
final ClientCleanup clientCleanup = new ClientCleanup() {
#Override
public void close() throws ConnectionException {
client.closeConnection();
}
};
// Resources are closed in the reverse order in which they are declared,
// so reverse the order of cleanup classes.
// For more details, see Java Langauge Specification 14.20.3 try-with-resources:
// https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.3
try (clientCleanup; containerCleanup; ioCleanup) {
// try-with-resources only used to ensure that all resources are cleaned up.
} catch (final ShutdownException e) {
throw new IOException("Handling ShutdownException: ", e);
} catch (final ConnectionException e) {
throw new IOException("Handling ConnectionException: ", e);
}
}
Of course this becomes even more elegant and concise with Java 8 lambdas:
public void close() throws IOException {
final Closeable ioCleanup = () -> super.close();
final ContainerCleanup containerCleanup = () -> container.shutdown();
final ClientCleanup clientCleanup = () -> client.closeConnection();
// Resources are closed in the reverse order in which they are declared,
// so reverse the order of cleanup classes.
// For more details, see Java Langauge Specification 14.20.3 try-with-resources:
// https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.20.3
try (clientCleanup; containerCleanup; ioCleanup) {
// try-with-resources only used to ensure that all resources are cleaned up.
} catch (final ShutdownException e) {
throw new IOException("Handling ShutdownException: ", e);
} catch (final ConnectionException e) {
throw new IOException("Handling ConnectionException: ", e);
}
}
This removes all the crazy nesting and it has the added benefit of saving the suppressed exceptions. In your case, if client.closeConnection() throws, we'll never know if the previous methods threw any exceptions. So the stacktrace will look something like this:
Exception in thread "main" java.io.IOException: Handling ConnectionException:
at Main$YourCloseable.close(Main.java:69)
at Main.main(Main.java:22)
Caused by: Main$ConnectionException: Failed to close connection.
at Main$Client.closeConnection(Main.java:102)
at Main$YourCloseable.close(Main.java:67)
... 1 more
By using try-with-resources, the Java compiler generates code to handle the suppressed exceptions, so we'll see them in the stacktrace and we can even handle them in the calling code if we want to:
Exception in thread "main" java.io.IOException: Failed to close super.
at Main$SuperCloseable.close(Main.java:104)
at Main$YourCloseable.access$001(Main.java:35)
at Main$YourCloseable $1.close(Main.java:49)
at Main$YourCloseable.close(Main.java:68)
at Main.main(Main.java:22)
Suppressed: Main$ShutdownException: Failed to shut down container.
at Main$Container.shutdown(Main.java:140)
at Main$YourCloseable$2.close(Main.java:55)
at Main$YourCloseable.close(Main.java:66)
... 1 more
Suppressed: Main$ConnectionException: Failed to close connection.
at Main$Client.closeConnection(Main.java:119)
at Main$YourCloseable$3.close(Main.java:61)
at Main$YourCloseable.close(Main.java:66)
... 1 more
Caveats
If the order of clean up matters, you need to declare your resource cleanup classes/lambdas in the reverse order that you want them run. I recommend adding a comment to that effect (like the one I provided).
If any exceptions are suppressed, the catch block for that exception will not execute. In those cases, it's probably better change the lambdas to handle the exception:
final Closeable containerCleanup = () -> {
try {
container.shutdown();
} catch (final ShutdownException e) {
// Handle shutdown exception
throw new IOException("Handling shutdown exception:", e);
}
}
Handling the exceptions inside the lambda does start to add some nesting, but the nesting isn't recursive like the original so it'll only ever be one level deep.
Even with those caveats, I believe the pros greatly outweigh the cons here with the automatic suppressed exception handling, conciseness, elegance, readability, and reduced nesting (especially if you have 3 or more resources to clean up).

Java AutoClosable behaviour in function

I have a sample code here. Will the FileInputStream created by the function, get automatically closed when the code exists the try/catch block of parentFunction ?
Or does it need to be explicitly closed in the someOtherFunction() itself ?
private void parentFunction() {
try {
someOtherFunction();
} catch (Exception ex) {
// do something here
}
}
private void someOtherFunction() {
FileInputStream stream = new FileInputStream(currentFile.toFile());
// do something with the stream.
// return, without closing the stream here
return ;
}
You have to use the resource with try-with-resource block.
Please read docs for AutoCloseable interface: https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html
method of an AutoCloseable object is called automatically when exiting a try-with-resources block for which the object has been declared in the resource specification header.
It needs to either be explicitly closed in the someOtherFunction() method, or used in a try-with-resources block:
private void someOtherFunction() {
try (FileInputStream stream = new FileInputStream(currentFile.toFile())) {
// do something with the stream.
} // the stream is auto-closed
}

Will this release my resources after being used?

Will this release my resources after being used?
InputStream inputStream;
try (InputStream unverifiedStream = connection.getInputStream()){
inputStream = unverifiedStream;
} catch (Exception e) {
e.printStackTrace();
}
//and use stream here to do other stuff with other streams
That will release your resources (close the stream) and leave you talking to a closed stream.
The assignment to inputStream does not copy the stream object. It copies the reference to the stream object. You now have two different ways to talk to the same object.
Since you are using a try-with-resource statement, and if by "released" you mean "closed" then yes.
Any instance implementing AutoCloseable opened in a try-with-resources statement is .close()d right before catch, so in your case unverifiedStream will be closed before you catch Exception.
It should also be noted that Closeable extends AutoCloseable, so all existing classes implementing Closeable will "magically" work within a try-with-resources statement.
Sample code:
public final class AutoCloseableExample
{
private static final class Foo
implements AutoCloseable
{
#Override
public void close()
throws IOException
{
System.out.println("foo");
throw new IOException();
}
}
public static void main(final String... args)
{
try (
final Foo foo = new Foo();
) {
System.out.println("try block");
} catch (IOException ignored) {
System.out.println("exception!");
} finally {
System.out.println("finally block");
}
}
}
Output:
try block
foo
exception!
finally block
Side note: you should not catch Exception since this also catches all unchecked exceptions (ie, RuntimeException and derivates). Catch more specific exceptions instead.
I haven't tried this, but I don't think it will compile if you try to use inputStream after the try-catch block, because inputStream won't be initialized if connection.getInputStream() throws an exception. Your catch block should assign a value or introduce a different flow of control to take care of that possibility.
If the try block completes normally, inputStream will refer to a closed stream outside the try-catch block, and most implementations will throw an exception on any operation you attempt on the stream.

What is the best way to emulate try-with-resources in Java 6?

It turns out that almost nobody closes resources in Java correctly. Programmers either do not use try-finally block at all, or just put resource.close() in finally which is also incorrect (because Throwable from close() can shadow Throwable from try block). Sometimes they put something like IOUtils.closeQuietly() with is only correct for InputStream, but not for OutputStream. try-with-resources solves all of these problems but there are still huge number of projects written in Java 6.
What is the best way to emulate try-with-resources in Java 6? Now I use Guava Closer, which is better than nothing but still much uglier than try-with-resources. Also, there is a pattern called a loan-pattern, but the absence of lambdas in Java makes this pattern very cumbersome. Is there a better way?
I've found a good replacement for try-with-resources. It uses Lombok library with annotation processing:
#Cleanup InputStream in = new FileInputStream(args[0]);
#Cleanup OutputStream out = new FileOutputStream(args[1]);
byte[] b = new byte[10000];
while (true) {
int r = in.read(b);
if (r == -1) break;
out.write(b, 0, r);
}
However, it doesn't handle exception correctly. This bug is more than 1 year old and still is not closed: https://code.google.com/p/projectlombok/issues/detail?id=384
Though anonymous class is quite verbose, it's still acceptable in java land
new TryWithResource<InputStream>(){
protected InputStream init() throws Exception {
return new FileInputStream("abc.txt");
}
protected void use(InputStream input) throws Exception{
input.read();
}
};
----
abstract class TryWithResource<R>
{
abstract protected R init() throws Exception;
abstract protected void use(R resource) throws Exception;
// caution: invoking virtual methods in constructor!
TryWithResource() throws Exception
{
// ... code before
R r = init();
use(r);
// ... code after
}
}
If your only problem with IOUtils.closeQuietly is that it ignores exceptions on OutputStreams, then you can either simply call close() on them, or create your own utility class which automatically treats the two differently, like this:
public static void close(Closeable resource)
{
try
{
resource.close();
}
catch(Exception e)
{
//swallow exception
}
}
public static void close(OutputStream o)
{
//throw any exceptions
o.close();
}
The correct overloaded method will be selected at compile time in all common situations, although if you're passing OutputStreams around as Closeables then you'll have to change this to do a dynamic instanceof check to make sure OutputStreams always throw exceptions.

implements Closeable or implements AutoCloseable

I'm in the process of learning Java and I cannot find any good explanation on the implements Closeable and the implements AutoCloseable interfaces.
When I implemented an interface Closeable, my Eclipse IDE created a method public void close() throws IOException.
I can close the stream using pw.close(); without the interface. But, I cannot understand how I can implement theclose() method using the interface. And, what is the purpose of this interface?
Also I would like to know: how can I check if IOstream was really closed?
I was using the basic code below
import java.io.*;
public class IOtest implements AutoCloseable {
public static void main(String[] args) throws IOException {
File file = new File("C:\\test.txt");
PrintWriter pw = new PrintWriter(file);
System.out.println("file has been created");
pw.println("file has been created");
}
#Override
public void close() throws IOException {
}
AutoCloseable (introduced in Java 7) makes it possible to use the try-with-resources idiom:
public class MyResource implements AutoCloseable {
public void close() throws Exception {
System.out.println("Closing!");
}
}
Now you can say:
try (MyResource res = new MyResource()) {
// use resource here
}
and JVM will call close() automatically for you.
Closeable is an older interface. For some reason To preserve backward compatibility, language designers decided to create a separate one. This allows not only all Closeable classes (like streams throwing IOException) to be used in try-with-resources, but also allows throwing more general checked exceptions from close().
When in doubt, use AutoCloseable, users of your class will be grateful.
Closeable extends AutoCloseable, and is specifically dedicated to IO streams: it throws IOException instead of Exception, and is idempotent, whereas AutoCloseable doesn't provide this guarantee.
This is all explained in the javadoc of both interfaces.
Implementing AutoCloseable (or Closeable) allows a class to be used as a resource of the try-with-resources construct introduced in Java 7, which allows closing such resources automatically at the end of a block, without having to add a finally block which closes the resource explicitly.
Your class doesn't represent a closeable resource, and there's absolutely no point in implementing this interface: an IOTest can't be closed. It shouldn't even be possible to instantiate it, since it doesn't have any instance method. Remember that implementing an interface means that there is a is-a relationship between the class and the interface. You have no such relationship here.
It seems to me that you are not very familiar with interfaces. In the code you have posted, you don't need to implement AutoCloseable.
You only have to (or should) implement Closeable or AutoCloseable if you are about to implement your own PrintWriter, which handles files or any other resources which needs to be closed.
In your implementation, it is enough to call pw.close(). You should do this in a finally block:
PrintWriter pw = null;
try {
File file = new File("C:\\test.txt");
pw = new PrintWriter(file);
} catch (IOException e) {
System.out.println("bad things happen");
} finally {
if (pw != null) {
try {
pw.close();
} catch (IOException e) {
}
}
}
The code above is Java 6 related. In Java 7 this can be done more elegantly (see this answer).
Here is the small example
public class TryWithResource {
public static void main(String[] args) {
try (TestMe r = new TestMe()) {
r.generalTest();
} catch(Exception e) {
System.out.println("From Exception Block");
} finally {
System.out.println("From Final Block");
}
}
}
public class TestMe implements AutoCloseable {
#Override
public void close() throws Exception {
System.out.println(" From Close - AutoCloseable ");
}
public void generalTest() {
System.out.println(" GeneralTest ");
}
}
Here is the output:
GeneralTest
From Close - AutoCloseable
From Final Block
Recently I have read a Java SE 8 Programmer Guide ii Book.
I found something about the difference between AutoCloseable vs Closeable.
The AutoCloseable interface was introduced in Java 7. Before that, another interface
existed called Closeable. It was similar to what the language designers wanted, with the
following exceptions:
Closeable restricts the type of exception thrown to IOException.
Closeable requires implementations to be idempotent.
The language designers emphasize backward compatibility. Since changing the existing
interface was undesirable, they made a new one called AutoCloseable. This new
interface is less strict than Closeable. Since Closeable meets the requirements for
AutoCloseable, it started implementing AutoCloseable when the latter was introduced.
The try-with-resources Statement.
The try-with-resources statement is a try statement that declares one or more resources. A resource is an object that must be closed after the program is finished with it. The try-with-resources statement ensures that each resource is closed at the end of the statement. Any object that implements java.lang.AutoCloseable, which includes all objects which implement java.io.Closeable, can be used as a resource.
The following example reads the first line from a file. It uses an instance of BufferedReader to read data from the file. BufferedReader is a resource that must be closed after the program is finished with it:
static String readFirstLineFromFile(String path) throws IOException {
try (BufferedReader br =
new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
In this example, the resource declared in the try-with-resources statement is a BufferedReader. The declaration statement appears within parentheses immediately after the try keyword. The class BufferedReader, in Java SE 7 and later, implements the interface java.lang.AutoCloseable. Because the BufferedReader instance is declared in a try-with-resource statement, it will be closed regardless of whether the try statement completes normally or abruptly (as a result of the method BufferedReader.readLine throwing an IOException).
Prior to Java SE 7, you can use a finally block to ensure that a resource is closed regardless of whether the try statement completes normally or abruptly. The following example uses a finally block instead of a try-with-resources statement:
static String readFirstLineFromFileWithFinallyBlock(String path)
throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
Please refer to the docs.

Categories