Can my AutoCloseable.close () function detect a potential exception?

When implementing AutoCloseableto work with the try-with-resources operator of Java 7, I would like to know if there was an exception in the try block. For example:.

class C implements AutoCloseable {
    @Override
    public void close() {
        if (exceptionOccurred)
            something();
        else
            somethingElse();
    }
}

To illustrate this:

try (C c = new C()) {

    // This should cause a call to "something()"
    if (something)
        throw new RuntimeException();

    // This should cause a call to "somethingElse()"
    else
        ;
}

Now, from understanding how the try-with-resources operator translates into bytecode , I think this is not possible. But is there any (reliable!) Trick using the toolkit / reflection / some undocumented compiler function that allows me to access the above RuntimeExceptionfrom AutoCloseable.close()?

Note. I am an API developer and I cannot control user code using APIs. Thus, the implementation must be performed on the AutoCloseablesite

+4
2

- try. :

try (CustomTransaction transaction = ...) {
    // Do something which might throw an exception...

    transaction.commitOnClose();
}

close , , , commitOnClose() .

, - .

+8

. Jon Skeet, ( ) commitOnClose(). , commit() rollback(), .

, , , :

TransactionEnforcer.DbResult<String> result = transactionEnforcer.execute(db -> {
  try {
    db.someFunctionThatThrowsACheckedException();
  } catch (TheException e) {
    return failure("fallback value");
  }
  return success(db.getAFancyValue());
});

result.ifPresent(v -> System.out.println(v));

, , , , java codepath , , .

:

package nl.knaw.huygens.timbuctoo.database;

import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;

public class TransactionEnforcer {
  private final Supplier<DbClass> dbClassFactory;

  public TransactionEnforcer(Supplier<DbClass> dbClassFactory) {
    this.dbClassFactory = dbClassFactory;
  }

  public <U> DbResult<U> execute(Function<DbClass, DbResult<U>> actions) {
    DbClass db = dbClassFactory.get();
    try {
      DbResult<U> result = actions.apply(db);
      if (result.isSuccess()) {
        db.close(true);
      } else {
        db.close(false);
      }
      return result;
    } catch (RuntimeException e) {
      db.close(false);
      throw e;
    }
  }

  public static class DbResult<T> {
    private final Optional<T> value;
    private final boolean success;

    private DbResult(T value, boolean success) {
      this.value = Optional.of(value);
      this.success = success;
    }

    public static <T> DbResult<T> success(T value) {
      return new DbResult<T>(value, true);
    }

    public static <T> DbResult<T> success() {
      return new DbResult<T>(null, true);
    }

    public static <T> DbResult<T> failure(T value) {
      return new DbResult<T>(value, false);
    }

    public static <T> DbResult<T> failure() {
      return new DbResult<T>(null, false);
    }

    public boolean isSuccess() {
      return success;
    }

    public Optional<T> getValue() {
      return value;
    }
  }
}

( DbClass )

+1

Source: https://habr.com/ru/post/1523707/


All Articles