V
V
Vasily Zhukov2013-02-06 00:58:30
Java
Vasily Zhukov, 2013-02-06 00:58:30

Throwable or Exception?

The other day I came up with a problem and, as it happens, I tried to solve it. There is a two part procedure. If there is an error between the first and second parts, you need to roll back the first one at all costs. If an error occurred during the second part, then you need to roll back the second part, and then the first and nothing else. As a result, the try/catch monster was born.

public void doAndForget() {
    try {
        service.doFirstPart();
        try {
            service.doSecondPart();
        } catch (Throwable t) {
            Log.warn(t);
            try {
                service.doRollbackSecondPart();
                try {
                    service.doRollbackFirstPart();
                } catch(Throwable t1) {
                    Log.error(t1);
                }
            } catch (Throwable t1) {
                Log.error(t1);
            }
        }
    } catch (Throwable t) {
        Log.warn(t);
        try {
            service.doRollbackFirstPart();
        } catch (Throwable t1) {
            Log.error(t1);
        }
    }
}

Why Throwable and not Exception? I'm afraid. Suddenly, some lib inside will throw NoClassDefFoundError or AssertionError, then we will not roll back. Yes, it seems like Error are errors that you don’t even need to try to fix, but I don’t want to fix an error, but what my code did before it. Yes, it seems like if OutOfMemoryError falls, then the current Thread should just die, but I want to at least try to restore the state of the application.
What will the opponents of catchThrowable say? Place catchException everywhere?

Answer the question

In order to leave comments, you need to log in

4 answer(s)
O
Oleg Yakovenko, 2013-02-06
@Apx

Why not simplify and remove a bunch of unnecessary try?

public void doAndForget() {
     boolean firstOk = false;
     boolean secondOk = false;
     try{
          firstOk = service.doFirst();
          if (firstOk){ //Если есть какая то жесткая зависимость исхода выполнения
               secondOk = service.doSecond();
          }
     } catch(Чего угодно){
          Log.warn("Status 1 task: "+ firstOk+"; 2nd task "+secondOk;
     } finally {
          //Проверить флаги и вызвать откаты в нужной последовательности
     }

}

And yet it’s better not to try to catch some NoClassDefFound or java.lang.OutOfMemoryError: PermGen space, in the latter case, there may already be any crap in memory that has not finalized gc or something. The data may no longer be valid or incorrect.

P
pletinsky, 2013-02-06
@pletinsky

I am not a java developer - so I apologize in advance, but this language seems to have a finally block, which was also invented for organizing rollbacks. What for to you to intercept errors to me at all it is not clear.
And judging by the wording of the try/finally task , there should be 2 blocks, not 5 like yours.
And as for the questions themselves - do not forget that there are situations in which you still lose confidence that you will be able to do a rollback - just like OutOfMemoryError - and your actions can lead to unexpected results. The application must be controlled.

R
relgames, 2013-02-07
@relgames

You can take a little functional approach and do, for example, like this

    public interface Transaction {
        void commit();
        void rollback();
    }

    public static void tryTransaction(Transaction tr) {
        try {
            tr.commit();
        } catch (Exception e) {
            //log.error....
            tr.rollback();
            throw new CommitException(...);
        }
    }

And here's how to use it:
        tryTransaction(new Transaction() {
            @Override
            public void commit() {
                //step1
                //...

                //step2
                tryTransaction(new Transaction() {
                    ...
                });
            }

            @Override
            public void rollback() {
            }
        });

Then the chain of rollbacks will line up itself. If an error occurs at the rollback stage, then the Exception will simply be passed above.

B
Beholder, 2013-02-26
@Beholder

In Java manuals, it is usually written that it is not worth intercepting Error and its subclasses, because if someone threw them out, it means that the system (JVM or program) is already broken so much at this moment that it is useless to recover.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question