Gostaria de dois têm dois métodos diferentes em execução em catch
e final
blocos. Eu descobri AutoCloseable
interface, mas eu preciso de algo para fogo em caso de única exceção.
Gostar:
SomeService service = CreateService().andOpenTransaction()
try {
service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
service.rollbackTransaction();
throw e;
} finally {
service.closeConnection();
}
Existe alguma maneira de torná-lo mais simples? Como eu disse eu estou familiarizado com AutoCloseable, mas isso me ajuda somente com bloco finally. Eu ainda não posso usá-lo dentro da captura.
Bem, você pode definir sua própria interface, e então algum static
método de corredor:
public interface ErrorHandlingCloseable extends AutoCloseable {
void run() throws Exception;
void onError(Exception e);
static void execute(ErrorHandlingClosable ehc) throws Exception {
try(ErrorHandlingClosable temp = ehc) {
ehc.run();
} catch(Exception e) {
ehc.onError(e);
throw e;
}
}
}
Que você então poderia então chamar assim:
SomeService service = CreateService().andOpenTransaction();
ErrorHandlingCloseable.execute(new ErrorHandlingCloseable() {
public void run() throws Exception { service.doSomeMessyThingsInsideDB(); }
public void onError(Exception e) { service.rollbackTransaction(); }
public void close() throws Exception { service.closeConnection(); }
});
Mas você vê, ainda é confuso.
Você pode até mesmo implementar isso interface
no seu SomeService
, mas, em seguida, você está restrito que o run()
método irá sempre chamar doSomeMessyThingsInsideDB()
.
Outro caminho, mas ainda semelhante seria usar Java8 e criar um ajudante funcional interface
:
public interface ThrowingRunnable {
void run() throws Exception;
}
E então um static
em algum lugar método:
public static void execute(ThrowingRunnable action,
ThrowingRunnable onCatch,
ThrowingRunnable onFinally) throws Exception {
try(AutoCloseable ao = onFinally) {
action.run();
} catch(Exception e) {
onCatch.run();
throw e;
}
}
A parte interessante é provavelmente esta: try(AutoCloseable ao = onFinally)
que "registros" o seu onFinally
método a ser chamado quando finally
é atingido.
Este poderia então ser chamado assim:
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);