Adam Bien's Weblog

Monday Sep 10, 2012

Conveniently, Transactionally and Legally Starting Runnables …With Java EE 6

EJB spec does not allow starting and managing threads:

The enterprise bean must not attempt to manage threads. The enterprise bean must not attempt to start, stop, suspend, or resume a thread, or to change a thread’s priority or name. The enterprise bean must not attempt to manage thread groups. [EJB 3.1 spec, page 599]

With Java EE 6 you don't have to create threads to execute a java.lang.Runnable asynchronously. Just implement an Executor as EJB 3.1:


import java.util.concurrent.Executor;
import javax.ejb.Asynchronous;
import javax.ejb.Stateless;

@Stateless
public class TransactionalExecutor implements Executor{

    @Override @Asynchronous
    public void execute(Runnable command) {
        command.run();
    }
}

Now inject the TransactionalExecutor as an Executor (the implementation of the Executor is optional, you could also directly inject the bean):


@Stateless
public class SlowService {
    
    @Inject
    Executor executor;
    
      
    public void invoke(){
        Runnable command = new Runnable() {

            @Override
            public void run() {
                    //some heavy work to do
            }
        };
        executor.execute(command);
    }
          
}


The Java EE 6 solution happens to be less simpler, than comparable Java SE implementation :-).

The async-worker Maven 3 project was pushed into http://kenai.com/projects/javaee-patterns/.

[The example is an excerpt from the "Real World Java EE Patterns" book (Second Iteration), page 167 in, chapter "Async Worker"]

See you at airhacks.com!


Special Event: Java 8 with Java EE 7: "More Power with Less Code", 13th October, 2014

A book about rethinking Java EE Patterns

Comments:

Hi Adam
Is there a way to implement something like the fork-join in Java EE?
It is legal to extends the ForkJoinPool to manage the ForkJoinTasks ?

Posted by Daniel on September 10, 2012 at 08:05 PM CEST #

Brilliant!

Posted by David Blevins on September 15, 2012 at 12:00 AM CEST #

It seems that the fact that your TransactionalExecutor implements Executor is irrelevant: TransactionalExecutor could implement another interface or not implement an interface at all. The only relevant bits are that 1) TransactionalExecutor is an SLSB, 2) has a method (execute(), in your example) that takes the block of code to execute as an argument (in the form of a Runnable, in your example) and that 3) that method is annotated with @Asynchronous. Correct?

Posted by Gerald Loeffler on September 22, 2012 at 03:42 PM CEST #

@Gerald,

+1. Forget about the Executor. It is just a nice extension,

thanks for your comment,

adam

Posted by Adam Bien on September 22, 2012 at 07:35 PM CEST #

Hi Adam,
I'm looking for a way to do the same in Java EE 5? Is JMS/MDB the only way to achieve it cleanly?

Posted by kweveen on October 24, 2012 at 04:59 PM CEST #

Adam i have a error running example in jboss 7.1
Caused by: java.lang.SecurityException: Prohibited package name: java.util.concurrent

Posted by Raul on December 04, 2012 at 11:27 PM CET #

Post a Comment:
  • HTML Syntax: NOT allowed
realworldpatterns.com
...the last 150 posts
...the last 10 comments
Links
License