Quisiera dos tienen dos métodos diferentes que se ejecutan en catch
y final
bloques. He encontrado AutoCloseable
interfaz, pero necesito algo de fuego en caso de única excepción.
Me gusta:
SomeService service = CreateService().andOpenTransaction()
try {
service.doSomeMessyThingsInsideDB();
} catch (Exception e) {
service.rollbackTransaction();
throw e;
} finally {
service.closeConnection();
}
¿Hay alguna forma para que sea más sencillo? Como ya he dicho estoy familiarizado con AutoCloseable, pero me ayuda únicamente con bloque finally. Todavía no puedo usarlo dentro de la captura.
Así se podría definir su propia interfaz, y algo static
método 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 luego se podría llamar así:
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(); }
});
Pero ya ves, que todavía está desordenado.
Incluso se puede poner en práctica este interface
en tu SomeService
pero entonces usted está restringida que el run()
método siempre llamará doSomeMessyThingsInsideDB()
.
Otra forma parecida, pero aún sería utilizar Java8 y crear un ayudante funcional interface
:
public interface ThrowingRunnable {
void run() throws Exception;
}
Y luego una static
en algún 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;
}
}
La parte interesante es probablemente la siguiente: try(AutoCloseable ao = onFinally)
que "registros" el onFinally
método que se llamará cuando finally
se alcanza.
Esto podría ser llamado como esto:
execute(
service::doSomeMessyThingsInsideDB,
service::rollbackTransaction,
service::closeConnection
);