Class Closer<E extends Exception>

java.lang.Object
org.hibernate.search.util.common.impl.AbstractCloser<Closer<E>,E>
org.hibernate.search.util.common.impl.Closer<E>
Type Parameters:
E - The supertype of exceptions this closer can catch and re-throw, besides RuntimeException and Error.
All Implemented Interfaces:
AutoCloseable

public final class Closer<E extends Exception> extends AbstractCloser<Closer<E>,E> implements AutoCloseable
A helper for closing multiple resources and re-throwing only one exception, suppressing the others as necessary.

This class is not thread safe.

This helper is mainly useful when implementing AutoCloseable.close() or a similar closing method in your own class, to make sure that all resources are at least given the chance to close, even if closing one of them fails. When creating then closing resources in the scope of a single method call, try-with-resource blocks should be favored.

See the AbstractCloser superclass for a list of methods allowing to close objects while catching exceptions.

Warning: In order not to ignore exceptions, you should always call close() once you closed all of your resources. The most straightforward way to do this is to use a try-with-resource block:


 public void myCloseFunction() throws MyException {
   try ( Closer<MyException> closer = new Closer<>() ) {
     closer.push( this.myCloseable::close );
     closer.pushAll( this.myListOfCloseables, MyCloseableType::close );
   }
 }
 

Exception type

Note that the closer has a generic type parameter, allowing it to re-throw a given checked exception. If you don't want to use this feature, you can simply use a Closer<RuntimeException>.

Splitting

If you need to close multiple resources throwing different checked exceptions, and those exceptions don't have a practical common superclass, you can "split" the closer:


 public void myCloseFunction() throws IOException, MyException, MyOtherException {
   try ( Closer<MyException> closer1 = new Closer<>();
       Closer<IOException> closer2 = closer1.split();
       Closer<MyOtherException> closer3 = closer1.split() ) {
     closer2.push( this.someJavaIOCloseable::close );
     closer1.pushAll( this.myListOfCloseables1, MyCloseableTypeThrowingMyException::close );
     closer3.pushAll( this.myListOfCloseables2, MyCloseableTypeThrowingMyOtherException::close );
   }
 }
 

The multiple closers will share the same state, which means the first exception to be caught by any of the closers will be the one to be re-thrown, and all subsequent exceptions caught by any closer will be added as suppressed to this first exception. Be careful though, you will have to close every single closer. Closing just the original one will not be enough.

  • Constructor Details

    • Closer

      public Closer()
  • Method Details

    • split

      public <E2 extends Exception> Closer<E2> split()
      Returns:
      A closer sharing the same state as this, allowing to handle multiple exception types.
      See Also:
    • close

      public void close() throws E
      Specified by:
      close in interface AutoCloseable
      Throws:
      E - The first throwable caught when executing the push methods, if any. Any throwable caught after the first will have been suppressed.