Nicola Cogotti

Co-Founder at Alpha Cogs

16 June 2018

Tomcat 8, despite is reliability and wide availability, suffers of some well (and sometimes less) known limitations as a Java EE server. This article explains how to takle some of these limitations using some of the new features available in Java 8, to develop an elegant and high performing solution to solve them.

Tomcat 8 is not a Java EE compliant server by design as it is a servlet container, however the servlet container is able to run EJB 3.0/JPA applications in application-managed Java SE (stand alone) mode.

This means that Tomcat will not offer many features that are out of the box using other Application Servers such as Glassfish, TomEE or Jboss; in particular, we will have the following limitations to JPA:

  • No dynamic weaving (instrumentation) - static weaving of entities is still available via EclipseLink

  • No @EJB injection of a session bean (containing the EntityManager) is available - use the persistence factory and manager directly

  • No @PersistenceContext injection is available- use

 

Persistence.createEntityManagerFactory(JTA_PU_NAME).

 

On the advantage side we have the fact that Tomcat (at the moment of writing 8.0.27.0) is a robust, relatively light and largely used server.

In some situations (depending the project, the client's infrastructure or other requirements) we may be in the position where we must use a non JEE compliant server but we still want to use and get advantage of an O.R.M. such as EclipseLink.

As seen in the points listed above this is still perfectly possible but more difficult as we will see.

First thing, we will not have the PersistenceContext injection that allowed us to simply write:

@PersistenceContext(unitName = "MyPU")

private EntityManager em;

to have an EntityManager instance.

In order to replicate it, as said before, we can manually create the EntityManagerFactory using:

Persistence.createEntityManagerFactory("MyPU").

The creation of the EntityManagerFactory is very expensive and we have to be very careful where and when we are going to create one.

The best approach is creating an EntityManagerUtil class that handles the creation for us:

This is a good solution and it is the one that many sites suggest to use. Now that we have our utility class we can use it to perform database queries using our favourite O.R.M. like in the example below:

Nice, it works! But... is it the best we can do?

Well, not really.

The system works and it is the "standard" way to integrate EclipseLink (or other O.R.M) using Tomcat but there are a couple of things that can be improved by just looking at the previous example.

  • The first thing we notice is that we have to handle every time for every insert or update an exception in order to perform the roll back

  • Every time we want to perform a transaction we always have to write 

entityManager.getTransaction().begin();    

    ......

entityManager.getTransaction().commit();
  • Something that most of people forget (and the example does not make exception to this) is that the EntityManager must be closed in order to free resources. Tomcat will not do it for us and leaving and entity manager connection open is one of the most common causes of resource leaks.

Here is where the new features of Java 8 can be used to improve the way we use our O.R.M.

The idea is trying to replicate what a JEE server does without having one.

Let's start from what we have called EntityManagerUtil and rewrite it in a different way:

There are two very interesting aspects here, the first one is the createScopedEntityManagerFactory function and the other one is the ScopedEntityManagerFactory.

The createScopedEntityManagerFactory uses the java.reflection.Proxy of Java 8.

From Java 8 documentation:

 

 "The method newProxyInstance takes three parameters: the classloader to use, an array of interfaces that the created proxy must implement, and the InvocationHandler to handle method calls with. It will create a new proxy class at runtime if none already exists, and return an instance of that class which dispatches method calls to the supplied InvocationHandler. Once a proxy class has been created for a particular classloader and set of interfaces, that class is cached and re-used – it is as efficient as a hand-rolled implementation of the bridge between the desired interface and InvocationHandler would have been." 

 

In this way we are simulating what a JEE compliant server does during the injection and the results in terms of performance are great. 

The ScopedEntityManagerFactory is a simple interface with just one method like the follow:

 

public interface ScopedEntityManagerFactory extends EntityManagerFactory {

public ScopedEntityManager createScopedEntityManager();

}

What is interesting here is that now we are in the position to define a EntityManagerFactoryHandler that will implements InvocationHandler.

In this class we will handle the situation when the method createScopedEntityManager will be called by the proxy even if EntityManagerFactoryHandler does not implement explicitly ScopedEntityManagerFactory (it is not important that we implement it, what's important is that we will handle the situation when the proxy will call the method).

Here is the code of EntityManagerFactoryHandler:

The most interesting part is the invoke method called by the proxy, and where createScopedEntityManager will be handled.

When this method is called we will reuse the Proxy.newProxyInstance similarly as seen before but this time we will use the ScopedEntityManager interface.

It is this part that will give us the real advantages and benefits compared to the "standard" way we have described at the beginning;

Let's see the interface ScopedEntityManager first :

ScopedEntityManager extends two classes:

EntityManager: This means that a ScopedEntityManager is an extension of an EntityManager offering some functions to manage transactions with the new Java 8 lambda expressions.

AutoClosable: This means that with try-with (Java 7) we will not need to worry about closing the EntityManager anymore because Java will do it for us avoiding resource leaks.

The last part is the implementation of the ScopedEntityManager that happens in EntityManagerHanlder.

EntityManagerHanlder will also implement InvocationHandler interface.

 

This is it! Now we are ready to perform operations to the DB.

Let's see a couple of examples:

Select a list of students:

Persist a student:

This is all we have to do, our ScopedEntityManager will take care for us to roll back transactions if an exception happens, close the connection with em at the end.

This method is also very nice because it gives us the possibility to log every single operation and know exactly what is going on for each call.

The loggers employed by both ScopedEntityManager and ScopedEntityManagerFactory handlers may be tweaked and customized as specified by the standard Java logging facility classes. They represent a useful debugging aid that allows the developer to monitor each database call, and may very well be disabled once the project is deployed, eliminating their overhead.