Lambda Expressions in Java, a Concrete Example

Maybe you have read several posts on the web on how Lambda Expressions are used. Most of the ones I have read uses examples for filtering collections with the new Stream API of Java 8. Those examples are good but they are more focused on showing a fancy way of filtering a collection rather than on showing or highlight the code structures that now you don’t have to write, in this case, the for loops. Without Lambda Expressions, each time you need to filter data from a collection, you have to iterate the collection (repeating a for loop construction). That is not necessary any more.

In this post I will show a concrete example of removing duplicated code using Lambda Expressions. For the demonstration I will be using JPA (Java Persistence API), following the topics of my previous post.

I believe that showing how to use Lambda Expressions putting the focus on the removal of duplicated code will open your mind on the potential that they have.

Suppose I’m asked to write some code to do a simple save, update and retrieve of a specific Entity class, using JPA. To implement that, I will write a class called ADataAccessObject (just to name it somehow). Below you will find what I have written in my first development iteration, the make it work step.

public class ADataAccessObject {

	private EntityManagerFactory emf;

	public ADataAccessObject(EntityManagerFactory emf) {
		this.emf = emf;
	}

	public void save(AnEntity anEntity) {
		EntityManager em = this.emf.createEntityManager();
		EntityTransaction tx = null;
		try {
			tx = em.getTransaction();
			tx.begin();

			em.persist(anEntity);

			tx.commit();
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			throw new RuntimeException(e);
		} finally {
			em.close();
		}
	}

	public void update(long id, String aNewPropertyValue) {
		EntityManager em = this.emf.createEntityManager();
		EntityTransaction tx = null;
		try {
			tx = em.getTransaction();
			tx.begin();

			AnEntity anEntity = em.find(AnEntity.class, id);
			anEntity.setAProperty(aNewPropertyValue);

			tx.commit();
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			throw new RuntimeException(e);
		} finally {
			em.close();
		}
	}

	public AnEntity byId(long id) {
		EntityManager em = this.emf.createEntityManager();
		try {
			return em.find(AnEntity.class, id);
		} catch (Exception e) {
			throw new RuntimeException(e);
		} finally {
			em.close();
		}
	}
}

Now lets write the client code that use the class above:

public class Main {
	public static void main(String arg[]) {
		EntityManagerFactory emf = null;
		try {
			emf = Persistence
					.createEntityManagerFactory("a-persistence-name");
			ADataAccessObject dao = new ADataAccessObject(emf);
			//store anEntity ...
			dao.store(new AnEntity("aValuForTheProperty"));
			//update anEntity ...
			dao.update(1l, "anotherValueForTheProperty");
			//retrieving ...
			AnEntity e = dao.byId(1l);
		} finally {
			emf.close();
		}
}

What does not look nice from the code above? As you might have noticed, each method seems to be pretty similar. The try/catch/finally block with the creation of the EntityManager, the Transaction#commit, Transaction#rollback and the EntityManager#close, all of these are duplicated.

To clarify a bit more, below are the sentences unique per method:

//from ADataAccessObject#store
em.persist(anEntity);

//from ADataAccessObject#update
AnEntity anEntity = em.find(AnEntity.class, id);
anEntity.setAProperty(aNewPropertyValue);

//from ADataAccessObject#byId
return em.find(AnEntity.class, id);

How can we remove that duplicated code? There are some options. You can use Dynamic Proxys or AspectJ. Or incorporate a framework like Spring to handle JPA Transactions for you. Do we have simpler approach? I don’t want to incorporate any framework, I would love the language itself provides the syntactical construction to do it.

What if the programming language allows you to pass a block of code as a method parameter? That sounds great, because I can create a private method in my ADataAccessObject class with the try/catch/finally structure and receive each unique block of sentences by parameter.

Before Java 8, this was possible using Anonymous Classes. Lets moving ahead with this approach then.

For implementing this approach we have to create an Interface to specify the signature of the block of code that we need to pass by parameter. Described next:

public interface ABlockOfCode {
	AnEntity execute(EntityManager em);
}

That Inteface above is the type of my block of code. Each block of code will respond to the execute method, it must receive the EntityManager by parameter and must return AnEntity.

Lets go through the second iteration of my code, the make it better step. I will refactor a bit my ADataAccessObject Class adding some anonymous classes to eliminate duplicated code.

public class ADataAccessObject {

	private EntityManagerFactory emf;

	public ADataAccessObject(EntityManagerFactory emf) {
		this.emf = emf;
	}

	public void store(AnEntity anEntity) {
		transactionExecute(new ABlockOfCode() {
			@Override
			public AnEntity execute(EntityManager em) {
				em.persist(anEntity);
				return null;
			}
		});
	}

	public void update(long id, String aNewPropertyValue) {
		transactionExecute(new ABlockOfCode() {
			@Override
			public AnEntity execute(EntityManager em) {
				AnEntity anEntity = em.find(AnEntity.class, id);
				anEntity.setAProperty(aNewPropertyValue);
				return null;
			}
		});
	}

	public AnEntity byId(long id) {
		return transactionExecute(new ABlockOfCode() {
			@Override
			public AnEntity execute(EntityManager em) {
				return em.find(AnEntity.class, id);			}
		});
	}

	private AnEntity transactionExecute(ABlockOfCode aBlockOfCode) {
		EntityManager em = this.emf.createEntityManager();
		EntityTransaction tx = null;
		try {
			tx = em.getTransaction();
			tx.begin();

			AnEntity a = aBlockOfCode.execute(em);

			tx.commit();
			return a;
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			throw new RuntimeException(e);
		} finally {
			em.close();
		}
	}
}

As you can see, I have created a private method called transactionExecute which expects as parameter an instance of ABlockOfCode. In each public method, I’m creating these instances, as anonymous classes, implementing the execute method of the ABlockOfCode with the sentences unique per method described before. Then, each method calls transactionExecute, passing these ABlockOfCode instances by parameter. Finally, note that inside the transactionExecute method, there is a call to the execute method of the ABlockOfCode instance, inside the try/catch/finally template.

Not bad right? Let’s do it now even better in my third development iteration. I’m going to replace the anonymous classes with Lambdas. In Java 8, Lambdas are a prettier way of writing anonymous classes (not the case for functional programming languages, but this is a different talk). They incorporate a syntactic sugar plus a type inference system, which make the code cleaner and easier to read.

The code below starts moving the transactionExecute private method to its own class.

public class TransactionTemplate {
	public EntityManagerFactory emf;

	public TransactionTemplate(EntityManagerFactory emf) {
		this.emf = emf;
	}

	public AnEntity execute(ABlockOfCode aBlockOfCode) {
		EntityManager em = this.emf.createEntityManager();
		EntityTransaction tx = null;
		try {
			tx = em.getTransaction();
			tx.begin();

			AnEntity returnValue = aBlockOfCode.execute(em);

			tx.commit();
			return returnValue;
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			throw new RuntimeException(e);
		} finally {
			em.close();
		}
	}
}

public class ADataAccessObject {

	private TransactionTemplate transaction;

	public ADataAccessObject(TransactionTemplate transaction) {
		this.transaction = transaction;
	}

	public void store(AnEntity anEntity) {
		transaction.execute(
			(em) -> { em.persist(anEntity);
								return null;
							});
	}

	public void update(long id, String aNewPropertyValue) {
		transaction.execute(
			(em) -> { AnEntity anEntity = em.find(AnEntity.class, id);
								anEntity.setAProperty(aNewPropertyValue);
								return null;
							});
	}

	public AnEntity byId(long id) {
		return transaction.execute(
			(em) -> {
								return em.find(AnEntity.class, id);
							});
	}
}

On the highlighted lines you will see the Lambda Expressions. A lambda expression, is composed of two parts, separated by the lexical token “->”: (parameters) -> { block of code }. There is no need to specify the type of the parameter in the lambda expression, it will be inferred from an interface, in this case, the ABlockOfCode. If you look at this interface you will note that each lambda expression receives an instance of the EntityManager as parameter, (em), and must return an instance of AnEntity.

As a final development iteration, I will make this more generic. My ABlockOfCode interface and TransactionTemplate class should support any object type, not only AnEntity. So next I will change the AnEntity type for a generic type T.

Starting with the ABlockOfCode interface:

public interface ABlockOfCode<T> {

	T execute(EntityManager em);
}

I have just replaced AnEntity with the generic type T, and I have declared that type T as a generic type, using the <T> syntax (on line 1).

Next, I will make the TransactionTemplate#execute method generic:

	public <T> T execute(ABlockOfCode<T> aBlockOfCode) {
		EntityManager em = this.emf.createEntityManager();
		EntityTransaction tx = null;
		try {
			tx = em.getTransaction();
			tx.begin();

			T returnValue = aBlockOfCode.execute(em);

			tx.commit();
			return returnValue;
		} catch (Exception e) {
			if (tx != null) {
				tx.rollback();
			}
			throw new RuntimeException(e);
		} finally {
			em.close();
		}
	}

On line 1, I’m declaring the generic type <T>, changing the signature of the method returning T and expecting ABlockOfCode<T> as parameter. Note also that the return type of the aBlockOfCode.execute(em) sentence, has change from AnEntity to T, on line 8.

With this last change we have made the TransactionTemplate#execute method generic to be used by any instance of ABlockOfCode that requires a JPA transaction context. The ADataAccessObject class does not need to change, because as I explained before, the Lambdas infer their type from the ABlockOfCode interface.

We just went through out some development iterations in order to remove duplicated code. This nature of the duplicated code shown here, is not able to be removed using simple refactoring techniques like extract method or extract class. It requires more powerful language feature to allow passing sentences, or blocks of code, by parameter. That was achieved using anonymous classes first and then with Lambda Expressions. And remember, don’t do refactoring iterations without test coverage.

Posted in Design & Architecture Tagged with: , ,