Java-EE-compatible AbstractExecutorService Implementation (Part 2)

Here is another take on my previous post—this time using a @Singleton EJB with bean-managed concurrency.  First, I introduce a valid interface, but one which is essentially identical to Executor, with the added restriction that execution must be asynchronous (while this is a common thing for “regular” Executors to do, it is not strictly speaking required of them).  I do this for the essential bits of @Asynchronous dispatching (once you see that code below you’ll see why).  While you could certainly use this as a business interface, I wouldn’t really expect you to.  Here’s the AsynchronousExecutor interface:

public interface AsynchronousExecutor {
  public void executeAsynchronously(final Runnable runnable);
}
And now the re-done ExecutorServiceBean:

@ConcurrencyManagement(ConcurrencyManagementType.BEAN)
@Local({Executor.class, ExecutorService.class, AsynchronousExecutor.class})
@Singleton
public class ExecutorServiceBean extends AbstractExecutorService implements ExecutorService, AsynchronousExecutor {

  @Resource
  private SessionContext sessionContext;

  @Override
  public void execute(final Runnable runnable) {
    if (runnable != null) {
      if (this.sessionContext != null) {
        final AsynchronousExecutor self = this.sessionContext.getBusinessObject(AsynchronousExecutor.class);
        assert self != null;
        self.executeAsynchronously(runnable);
      } else {
        runnable.run();
      }
    }
  }

  @Asynchronous
  @Override
  public void executeAsynchronously(final Runnable runnable) {
    if (runnable != null) {
      runnable.run();
    }
  }

  @Override
  public boolean awaitTermination(final long timeout, final TimeUnit unit) {
    return false;
  }

  @Override
  public boolean isTerminated() {
    return false;
  }

  @Override
  public boolean isShutdown() {
    return false;
  }

  @Override
  public void shutdown() {

  }

  @Override
  public List<Runnable> shutdownNow() {
    return Collections.emptyList();
  }

}

I made a couple of changes:
  • First, I took advantage of the fact that
    AbstractExecutorService actually arranges all the work for you such that really all you have to override is the Executor#execute(Runnable) method.  Specifically, I no longer override the AbstractExecutorService#submit(Callable) method.
  • Second, I made sure that the invocation of the execute(Runnable) method is not itself declared to be @Asynchronous, but delegates this call to the executeAsynchronously(Runnable) method, which is declared to be @Asynchronous.  This is because the innards of the AbstractExecutorService class call the execute(Runnable) method directly.  Since the asynchronous behavior of an @Asynchronous-annotated method can only be accomplished if the control flow progresses through the container, this cumbersome construct is necessary.  One big assumption I made here is that access to the SessionContext object is already properly synchronized by the container, so I performed no additional locking here.  I didn’t find anything in the EJB specification to support or contradict this assumption.
  • The bean is now a @Singleton with bean-managed concurrency.  Even though it has bean-managed concurrency, there are no explicit synchronization primitives anywhere, because they are locked up (ha ha) inside the AbstractExecutorService innards, which do whatever they do, in disturbingly precise and awesome Doug Lea fashion.
  • The bean’s set of @Local business interfaces now includes AsynchronousExecutor.class, so that the container dispatch by way of SessionContext#getBusinessObject(Class) can work.  Like I said earlier, you could use this as a business interface, but it probably would be excessively narrow.
Thanks for all the comments and input.
Advertisements

One thought on “Java-EE-compatible AbstractExecutorService Implementation (Part 2)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s