Digamos que eu tenha o GerarPedidoHandler que vá receber como parâmetro a lista de ações que ele precise executar. Caso algumas das ações falhe, eu precise fazer um rollback em todas as ações anteriores e não execute as próximas. Nesse caso, ainda vale a pena passar as ações por parâmetro? Eu implementei isso mas achei a solução feia e não sei até que ponto está correta.
// Nesse exemplo, a ação EnviarEmail lançará uma exceção
class TesteGeraPedido {
public static void main(String[] args) {
List<AcoesAposGerarPedido> listaAcoes = Arrays.asList(new SalvarNoBanco(new EnviarEmail(null)));
GeraPedidoHandler geraPedidoHandler = new GeraPedidoHandler(listaAcoes);
GeraPedido pedido = new GeraPedido("vitor", 5);
geraPedidoHandler.handle(pedido);
}
}
//------------------------------------------------------------------//
public class GeraPedidoHandler {
List<AcoesAposGerarPedido> acoes;
public GeraPedidoHandler(List<AcoesAposGerarPedido> acoes) {
this.acoes = acoes;
}
public void handle(GeraPedido geraPedido){
acoes.forEach(acao -> acao.executarTarefa(geraPedido));
}
}
//------------------------------------------------------------------//
public abstract class AcoesAposGerarPedido {
AcoesAposGerarPedido proximaAcao;
public AcoesAposGerarPedido(AcoesAposGerarPedido proximaAcao) {
this.proximaAcao = proximaAcao;
}
protected abstract void executar(GeraPedido geraPedido) throws Exception;
protected abstract void desfazer(GeraPedido geraPedido);
public void executarTarefa(GeraPedido geraPedido){
try{
executar(geraPedido);
if(proximaAcao != null)
proximaAcao.executarTarefa(geraPedido);
}catch (Exception e){
desfazer(geraPedido);
// Caso a próxima Acao não tenha sido executada, ele irá desfazer mesmo assim, o que não faz sentido
if(proximaAcao!= null)
proximaAcao.desfazer(geraPedido);
throw new RuntimeException(e);
}
}
}
//------------------------------------------------------------------//
public class EnviarEmail extends AcoesAposGerarPedido {
public EnviarEmail(AcoesAposGerarPedido acaoAnterior) {
super(acaoAnterior);
}
@Override
protected void executar(GeraPedido geraPedido) throws Exception {
System.out.println("Email enviado");
throw new Exception("erro ao enviar email");
}
@Override
protected void desfazer(GeraPedido geraPedido) {
System.out.println("Email desfeito!");
}
}
//------------------------------------------------------------------//
public class SalvarNoBanco extends AcoesAposGerarPedido{
public SalvarNoBanco(AcoesAposGerarPedido acaoAnterior) {
super(acaoAnterior);
}
@Override
protected void executar(GeraPedido geraPedido) {
System.out.println("Salvou no banco");
}
@Override
protected void desfazer(GeraPedido geraPedido) {
System.out.println("Desfez operação no banco");
}
}
//------------------------------------------------------------------//