34

I am having a hard time not to repeat myself in a Java program I am working on at the moment.

Say, I need to declare a lot of methods that basically are structured in the following way:

public SomeEntity doSomething (String someAttribute, String anotherAttribute) {
    EntityManager em = this.createEntityManager();

    EntityTransaction tx = null;
    try {

        /*
         * ... independent logic ...
         */

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

    return something;
}

The method body of all methods needs to contain theses elements for resource management.

The "independent logic" itself will be rather complex too, so putting the try/catch statement in a separate method won't really work.

I want to avoid to repeat this code. What are the best practices to apply in these situations?

mritz_p
  • 3,008
  • 3
  • 28
  • 40
  • 7
    Perhaps try-with-resources might help you -- http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html – Anders R. Bystrup Aug 12 '14 at 08:13
  • 8
    This is where the "Execute around" pattern can help: http://stackoverflow.com/questions/341971/what-is-the-execute-around-idiom – nos Aug 12 '14 at 08:15
  • Hey @AndersR.Bystrup, thank you very much. I have to admit I didn't know, try-with-resources existed. Unfortunately `javax.persistence.EntityManager` doesn't implement `AutoClosable`. – mritz_p Aug 12 '14 at 08:18
  • 4
    Then wrap it into an object that implements `AutoClosable` :). I.e. your `createEntitiyManager` method returns `ClosableEntitiyManager` which is a wrapper around `EntityManager` that implements `AutoClosable`, and you are all done. – Domi Aug 12 '14 at 08:26
  • 1
    Another way to solve this problem is to use Spring. You declare a method that is annotated with `@Transactional` and all the transaction work is done for you. – Arnaud Denoyelle Aug 12 '14 at 08:29
  • Decorators, that are not released yet, would be useful here. See https://github.com/tc39/proposals#stage-2 – Constantin De La Roche Sep 07 '20 at 12:33

9 Answers9

35

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?

Community
  • 1
  • 1
nos
  • 223,662
  • 58
  • 417
  • 506
  • 2
    OK -one glaring issue... How will tx ever be NOT NULL when any exception occurs??? The last place where an exception can occur is the assignemnt em.getTransaction() if this throws, em is still null, if not your try-block is over o_O – Falco Aug 12 '14 at 09:52
  • 5
    Yes - that's certainly the case - though the part is verbatim from the original code - so the OP will have to structure it to what is actually needed. – nos Aug 12 '14 at 10:09
  • It is worth noting that `something` will not be accessible from within `execute`. – mritz_p Aug 12 '14 at 19:56
  • In Java 8, you can replace `new EntityManagerAction() { public void execute(EntityManager em) { ... } }` by `(em) -> { ... }`, as EntityManagerAction is a functional interface. Alternatively, you could pass it a method reference `this::doStuff`, where `doStuff` looks like `void doStuff(EntityManager em) { ... }`. – Mangara Aug 13 '14 at 05:07
8

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;
}
ethanfar
  • 3,733
  • 24
  • 43
  • What do you think of the idea of having a local variable of type `Exception`, which is initially null, and having a `catch` block set the variable and re-throw? The `finally` block could then perform logic which should execute unconditionally, only in the `succeed` case, and only in the `fail` case, in whatever order was required. Note that the compiler would end up duplicating the code for the `finally` block, but at least it wouldn't have to be duplicated in the source code. – supercat Aug 12 '14 at 16:56
3

I would create a abstraction of the independent logic, say Job, and the doSomething() will become processJob() in a Service class. The you will be calling your processJob() for every processing and the all the code from your example except the independent logic will be written exactly once.

Edit: Which is what nos suggested in comment: What is the "Execute Around" idiom?

Community
  • 1
  • 1
Jan Zyka
  • 17,460
  • 16
  • 70
  • 118
3

We recently faced an issue like this, and decided to go with the callback design pattern.

So, if all of the methods have similar code and it's just the independant logic that is different, you could create an interface whose implementations handle the independent code. So something like this:

public SomeEntity doSomething (String someAttribute, String anotherAttribute) {
       return (SomeEntity)callbackMethod(someAttribute, anotherAttribute, new IndependentCodeInterfaceImpl1());
}

public SomeOtherEntity doSomethingElse (String someAttribute, String anotherAttribute) {
    return (SomeOtherEntity)callbackMethod(someAttribute, anotherAttribute, new IndependentCodeInterfaceImpl2());
}

private Object callbackMethod(String someAttribute, String anotherAttribute, IndependentCodeInterface independent) {
    EntityManager em = this.createEntityManager();
    EntityTransaction tx = null;
    Object response = null;
    try {
        response = independent.execute(someAttribute, anotherAttribute, em);
        tx = em.getTransaction();
    } catch (RuntimeException e) {
        if (tx != null && tx.isActive()) { 
            tx.rollback();
        }
        throw e;
    } finally {
        em.close();
    }
    return response;
}
Ben Green
  • 3,953
  • 3
  • 29
  • 49
3

If you are using a JavaEE application server than your code can be simplified dramatically by using a stateless session bean:

@Stateless
public class SomethingFactory {

    @PersistenceContext
    private EntityManager em;

    public SomeEntity doSomething (String someAttribute, String anotherAttribute) {
       /*
        * ... independent logic ...
        */
       return something;
    }

}

The container will look after all the transaction management semantics for you.

Steve C
  • 18,876
  • 5
  • 34
  • 37
2

you can make your method signatures return the exception

 public SomeEntity doSomething (String someAttribute, String anotherAttribute) throws RuntimeException {
// your independent logic
}

 public SomeEntity doSomethingElse (String someAttribute, String anotherAttribute) throws RuntimeException {
// your independent logic
}

 public SomeEntity doSomethingDifferent (String someAttribute, String anotherAttribute) throws RuntimeException {
// your independent logic
}

then you can handle it in a seperate method:

   public String yourHandleMethod(){
String something = "";
EntityManager em = this.createEntityManager();

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

    return something;
Arno_Geismar
  • 2,296
  • 1
  • 15
  • 29
  • Hi @Arno_Geismar, thank you very much! The problem is not really the sequential execution of methods though. – mritz_p Aug 12 '14 at 08:25
2

You can implement a mechanism similar to Spring Transaction Template.

First, implement a callback which will be implemented for each business operation, providing both the entity manager and transaction:

public static interface TransactionCallback<R> {
  R doInTransaction(EntityManager em, EntityTransaction tx);
}

Then, create a generic method with the boilerplate code:

public <T> T execute(TransactionCallback<T> callback) {
  EntityManager em = this.createEntityManager();
  EntityTransaction tx = null;

  try {
    tx = em.getTransaction();
    return callback.doInTransaction(em, tx);
  } catch (RuntimeException e) {
    if (tx != null && tx.isActive()) { 
        tx.rollback();
    }
    throw e;
  } finally {
    em.close();
  }
}

Finally, you can create business logic similar to this:

public SomeEntity doSomething(String someAttribute, String anotherAttribute) {
  return execute(new TransactionCallback<SomeEntity>() {
    @Override
    public SomeEntity  doInTransaction(EntityManager em, EntityTransaction tx) {
      // do something here
    }
  });
}

This approach have several advantages. It is clean and you can intercept all actions on one place - for example: add logging, etc.

I am sorry for any syntax errors, I am writing it without IDE. But you get the idea.

EDIT: Maybe it can be shorter using lambdas in JDK 8, because TransactionCallback might be functional interface :).

voho
  • 2,805
  • 1
  • 21
  • 26
2

For completeness - there's the Template Method Pattern. It allows you to abstract all of the management code out of a procedure and just implement the core function. This pattern is especially useful when you have a number of meta-requirements such as closing stuff while correctly handling exceptions.

I use this pattern for, among other things, running database queries because of all of the rules about being sure to close all ResultSets and Connections while still correctly managing PreparedStatements.

abstract class DoSomethingWithEntity {

    public SomeEntity doSomething(String someAttribute, String anotherAttribute) {
        SomeEntity something;
        EntityManager em = createEntityManager();

        EntityTransaction tx = null;
        try {
            tx = em.getTransaction();
            // Call the abstract stuff that can be different.
            something = doIt(em, tx);
        } catch (RuntimeException e) {
            if (tx != null && tx.isActive()) {
                tx.rollback();
            }
            throw e;
        } finally {
            em.close();
        }

        return something;
    }

    // The bit you want to write yourself. Make it abstract so you have to write it.
    abstract SomeEntity doIt(EntityManager em, EntityTransaction tx) throws Exception;
}

public void test() {
    SomeEntity e = new DoSomethingWithEntity() {

        @Override
        SomeEntity doIt(EntityManager em, EntityTransaction tx) {
            // Do your stuff here.
            return new SomeEntity();
        }

    }.doSomething("someAttribute", "anotherAttribute");
}

Note that you don't have to make all exceptions into RuntimeException - you can define explicitly what exceptions are allowed to be thrown.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
1

FYI - the new lambda expressions feature in JDK 1.8 is now the most elegant way to solve this problem. Your DoSomething method would just be something like this:

DataExecutor.execute(() -> {
    // let's say your "independent logic" is the following three statements
    statementA;
    statementB;
    statementC;
});

Your DataExecutor.execute method would look something like this (you'll maybe want a return type):

public static void execute(work)
{
    EntityManager em = this.createEntityManager();

    EntityTransaction tx = null;
    try {

        // this is the "independent logic" you passed in via the "work" lambda
        work.doWork();

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

And lastly, you'll need to define a (or use an existing) functional interface:

@FunctionalInterface
public interface DataFuncVoid {
    public abstract void doWork();
}
Bill Joyce
  • 11
  • 1