How to not repeat code within catch blocks?

If all your finally clauses are used to close Streams and such (anything that implements AutoCloseable), you can use try-with-resources (as suggested in one of the comments) to get rid of the finally clause.

However, if you need a more generic solution, and have the same type of Exceptions caught and the same sort of handling in the finally clause, you can create an abstract class such as:

abstract class SensitiveBlockHandler {
    public void handle() {
        try {
            doHandling();
        } catch (SomeException | AnotherException e) {
            // TODO: handle exceptions here ...
        } finally {
            // TODO: cleanup here ...
        }
    }

    protected abstract void doHandling();
}

Then, you can create inner classes to handle the different situations, either as anonymous classes or not. The code should look something like:

public SomeEntity doSomething (String someAttribute, String anotherAttribute) {
    new SensitiveBlockHandler() {
        protected void doHandling() {
            /*
             * ... independent logic ...
             */
        }
    }.handle();

    return something;
}

Create an interface:

public interface EntityManagerAction {
   public void execute(EntityManager em);
}

And a utility class:

public class EntityUtil {
  public static void executeWithEntityManager(EntityManagerAction action) {
    EntityManager em = someHowCreateEntityManager();

    EntityTransaction tx = null;
    try {
        action.execute(em);
        tx = em.getTransaction();
    } catch (RuntimeException e) {
        if (tx != null && tx.isActive()) { 
            tx.rollback();
        }
        throw e;
    } finally {
        em.close();
    }
  }
}

Now you can re-use the boiler-plate in the EntityUtil class, and your code becomes:

public SomeEntity doSomething (String someAttribute, String anotherAttribute) {
   Something something; 
   EntityUtil.executeWithEntityManager(new EntityManagerAction() {
        public void execute(EntityManager em ) {

        /*
         * ... independent logic ...
         */
         //use the passed in 'em' here.
        }
    });

    return something;
}

See also What is the "Execute Around" idiom?

Tags:

Java