CloseableScope

CloseableScope is a tiny Java library that implements single interface CloseableScope, which is an unchecked version of AutoCloseable.

Download

Get CloseableScope from Maven Central:

Tool
<dependency>
    <groupId>com.machinezoo.closeablescope</groupId>
    <artifactId>closeablescope</artifactId>
    <version>1.0.1</version>
</dependency>

Or clone sources from GitHub or Bitbucket. Don't forget to configure your build for Java 11+. Sources and binaries are distributed under Apache License 2.0.

If your project is a Java module, add the following declaration to your module-info.java:

requires com.machinezoo.closeablescope;

Usage

CloseableScope is intended for creating custom scoping rules that ensure some code runs at the end of the scope, for example:

static CloseableScope test() {
    System.out.println("Open scope.");
    return () -> System.out.println("Close scope.");
}

static void main(String args[]) {
    try (var scope = test()) {
        System.out.println("Run in scope.");
    }
}

This produces the following output:

Open scope.
Run in scope.
Close scope.

Closing code runs even if exception is thrown in the try-with-resources block. The above code is equivalent to try-finally block:

System.out.println("Open scope.");
try {
    System.out.println("Run in scope.");
} finally {
    System.out.println("Close scope.");
}

Nesting

You can of course nest try-with-resources blocks, but sometimes inner scope must be automatically opened together with outer scope, for example when the outer scope extends functionality of the inner scope. CloseableScope offers method andFinally(Runnable) for this purpose.

static CloseableScope inner() {
    System.out.println("Open inner.");
    return () -> System.out.println("Close inner.");
}

static CloseableScope outer() {
    System.out.println("Open outer.");
    var inner = inner();
    return inner.andFinally(() -> System.out.println("Close outer."));
}

static void main(String args[]) {
    try (var scope = outer()) {
        System.out.println("Run in scope.");
    }
}

This produces the following output:

Open outer.
Open inner.
Run in scope.
Close inner.
Close outer.

Outer closing code will run even if the inner closing code throws. There's also andThen(Runnable) method, which differs in this detail.

Alternatives

There are a few alternatives to this library, each with its tradeoffs:

Next steps