Archive | February 2014

Using Java EE’s ManagedExecutorService to asynchronously execute transactions

One year has passed by since the Java EE 7 specification has been published. Now that Wildfly 8 Final has been released, it is time to take a closer look at the new features.

One thing which was missing since the beginning of the Java EE days is the ability to work with fully-fledged Java EE threads. Java EE 6 has already brought us the @Asynchronous annotation with which we could execute single methods in the background, but a real thread pool was still out of reach. But all this is now history since Java EE 7 introduced the ManagedExecutorService:

@Resource
ManagedExecutorService managedExecutorService;

Like the well-known ExecutorService from the Standard Edition, the ManagedExecutorService can be used to submit tasks that are executed within a thread pool. One can choose if the tasks submitted should implement the Runnable or Callable interface.

In contrast to a normal SE ExecutorService instance, the ManagedExecutorService provides threads that can access for example UserTransactions from JNDI in order to execute JPA transactions during their execution. This feature is a huge difference to threads started like in a SE environment.

It is important to know, that the transactions started within the ManagedExecutorService’s thread pool run outside of the scope of the transaction of the thread which submits the tasks. This makes it possible to implement scenarios in which the submitting thread inserts some information about the started tasks into the database while the long-running tasks execute their work within an independent transaction.

Now, after we have learned something about the theory, let’s put our hands on some code. First we write a @Stateless EJB that gets the ManagedExecutorService injected:

@Stateless
public class MyBean {
    @Resource
    ManagedExecutorService managedExecutorService;
    @PersistenceContext
    EntityManager entityManager;
    @Inject
    Instance<MyTask> myTaskInstance;

    public void executeAsync() throws ExecutionException, InterruptedException {
        for(int i=0; i<10; i++) {
            MyTask myTask = myTaskInstance.get();
            this.managedExecutorService.submit(myTask);
        }
    }

    public List<MyEntity> list() {
        return entityManager.createQuery("select m from MyEntity m", MyEntity.class).getResultList();
    }
}

The tasks that we will submit to the ManagedExecutorService are retrieved from CDI’s Instance mechanism. This lets us use the power of CDI within our MyTask class:

public class MyTask implements Runnable {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyTask.class);
    @PersistenceContext
    EntityManager entityManager;

    @Override
    public void run() {
        UserTransaction userTransaction = null;
        try {
            userTransaction = lookup();
            userTransaction.begin();
            MyEntity myEntity = new MyEntity();
            myEntity.setName("name");
            entityManager.persist(myEntity);
            userTransaction.commit();
        } catch (Exception e) {
            try {
                if(userTransaction != null) {
                    userTransaction.rollback();
                }
            } catch (SystemException e1) {
                LOGGER.error("Failed to rollback transaction: "+e1.getMessage());
            }
        }
    }

    private UserTransaction lookup() throws NamingException {
        InitialContext ic = new InitialContext();
        return (UserTransaction)ic.lookup("java:comp/UserTransaction");
    }
}

Here we can inject the EntityManager to persist some entities into our database. The UserTransaction that we need for the commit has to be retrieved from the JNDI. An injection using the @Resource annotation is not possible within a normal managed bean.

To circumvent the UserTransaction we could of course call the method of another EJB and use the other EJB’s transaction to commit the changes to the database. The following code shows an alternative implementation using the injected EJB to persist the entity:

public class MyTask implements Runnable {
    private static final Logger LOGGER = LoggerFactory.getLogger(MyTask.class);
    @PersistenceContext
    EntityManager entityManager;
    @Inject
    MyBean myBean;

    @Override
    public void run() {
		MyEntity myEntity = new MyEntity();
        myBean.persit(myEntity);
    }
}

Now we only need to utilize JAX-RS to call the functionality over a REST interface:

@Path("/myResource")
public class MyResource {
    @Inject
    private MyBean myBean;

    @Path("list")
    @GET
    @Produces("text/json")
    public List<MyEntity> list() {
        return myBean.list();
    }

    @Path("persist")
    @GET
    @Produces("text/html")
    public String persist() throws ExecutionException, InterruptedException {
        myBean.executeAsync();
        return "<html><h1>Successful!</h1></html>";
    }
}

That’s it. With these few lines of code we have implemented a fully working Java EE application whose functionality can be called over a REST interface and that executes its core functionality asynchronously within worker threads with their own transactions.

Conclusion: The ManagedExecutorService is a great feature to integrate asynchronous functionality using all the standard Java EE features like JPA and transactions into enterprise applications. I would say the waiting was worthwhile.

Example source code can be found on github.

Injecting configuration values using CDI’s InjectionPoint

Dependency injection is a great technology for the organization of class dependencies. All class instances you need in your current class are provided at runtime from the DI container. But what about your configuration?

Of course, you can create a “Configuration” class and inject this class everywhere you need it and get the necessary value(s) from it. But CDI lets you do this even more fine-grained using the InjectionPoint concept.

If you write a @Produces method you can let your CDI container also inject some information about the current code where the newly created/produced value is inject into. A complete list of the available methods can be found here. The interesting point is, that you can query this class for all the annotations the current injection point has:

Annotated annotated = injectionPoint.getAnnotated();
ConfigurationValue annotation = annotated.getAnnotation(ConfigurationValue.class);

As the example code above shows, we can introduce a simple @Qualifier annotation that marks all the injection points where we need a specific configuration value. In this blog post we just want to use strings as configuration values, but the whole concept can of course be extended to other data types as well. The already mentioned @Qualifier annotation looks like the following one:

@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface ConfigurationValue {
	@Nonbinding ConfigurationKey key();
}

public enum ConfigurationKey {
	DefaultDirectory, Version, BuildTimestamp, Producer
}

The annotation has of course the retention policy RUNTIME because the CDI container has to evaluate it while the application is running. It can be used for fields and methods. Beyond that we also create a key attribute, which is backed by the enum ConfigurationKey. Here we can introduce all configuration values we need. In our example this for example a configuration value for a default directory, for the version of the program and so on. We mark this attribute as @Nonbinding to prevent that the value of this attribute is used by the CDI container to choose the correct producer method. If we would not use @Nonbinding we would have to write a @Produces method for each value of the enum. But here we want to handle all this within one method.

The @Produces method for strings that are annotated with @ConfigurationKey is shown in the following code example:

@Produces
@ConfigurationValue(key=ConfigurationKey.Producer)
public String produceConfigurationValue(InjectionPoint injectionPoint) {
	Annotated annotated = injectionPoint.getAnnotated();
	ConfigurationValue annotation = annotated.getAnnotation(ConfigurationValue.class);
	if (annotation != null) {
		ConfigurationKey key = annotation.key();
		if (key != null) {
			switch (key) {
				case DefaultDirectory:
					return System.getProperty("user.dir");
				case Version:
					return JB5n.createInstance(Configuration.class).version();
				case BuildTimestamp:
					return JB5n.createInstance(Configuration.class).timestamp();
			}
		}
	}
	throw new IllegalStateException("No key for injection point: " + injectionPoint);
}

The @Produces method gets the InjectionPoint injected as a parameter, so that we can inspect its values. As we are interested in the annotations of the injection point, we have a look if the current injection point is annotated with @ConfigurationValue. If this is the case, we have a look at the @ConfigurationValue’s key attribute and decide which value we return. That’s it. In a more complex application we can of course load the configuration from some files or some other kind of data store. But the concept remains the same.

Now we can easily let the CDI container inject the configuration values we need simply with these two lines of code:

    @Inject @ConfigurationValue(key = ConfigurationKey.DefaultDirectory)
    private String defaultDirectory;

Conclusion: Making a set of configuration values accessible throughout the whole application has never been easier.