How to interrupt or set a time limit for an EJB method invocation on JBoss EAP6

Solution Verified - Updated

Environment

  • JBoss Enterprise Application Platform 6

Issue

  • I set jnp.timeout but the method on the server side is still executed until it is finished
  • Is it possible to set a timeout for RMI calls
  • How can I set a time limit for an EJB invocation without break the EJB specification (don't start Threads)

Resolution

Since EJB 3.1 this can be achieved by using asynchronous method invocations.
There is a simple example 'ejb-asynchronous' within the quickstarts, see Content from docs.jboss.org is not included.documentation or Content from www.jboss.org is not included.the JBoss Way - quickstarts.
If it is not desired that the client have to handle it the asyncronous call can be wrapped inside the application:

public <T> aInvocation(params ...) throws TimeoutException {
  Future<T> result = aAsyncBean.aInvocation(params ...);
  <T> value = result.get(myTimeout);
  if(result.isDone()) {
    return value;
  } else {
    throw TimeoutException();
  }
}

Calling cancel will attempt to cancel the EJB invocation as descirbed in [1]:

Call the cancel(boolean mayInterruptIfRunning) method on the Future<V> instance to attempt to cancel the method invocation. The cancel method returns true if the cancellation was successful, and false if the method invocation cannot be cancelled.

Another possibility is a global property for the ejb-client introduced with the new ejb-client of EAP6. This invocation.timeout will cause the client to timeout if the EJB invocation does not complete in a given time, but it does not intertupt the EJB if it is already processing the request, in this case the client will get an exception back but the EJB will continue to run until finish and then EJB will log an error saying it was unable to send a response to the client. For more details see KCS solution 1472333 - EJB execution timeout

To have the EJB method be interrupted, the EJB code must check for cancellation, via SessionContext.wasCallCancelled(). This is onyl possible if it performs work in a loop or has multiple steps. If the EJB makes a long blocking call to other API (for example JDBC) it cannot be interrupted. For example:

  @Resource private SessionContext sessionContext;

  void checkCancellation() {
    if (sessionContext.wasCallCancelled()) {
      throw new RuntimeException("Cancelled");
    }
  }

  @Asynchronous
  Future<...> someMethod() {
    while (condition) {
      checkCancellation();
      ... do work ...
    }
  }

  @Asynchronous
  Future<...> someMethod() {
    ... do work ...
    checkCancellation();
    ... do more work ...
    checkCancellation();
    ... do more  work ...
  }

Content from docs.oracle.com is not included.[1] Content from docs.oracle.com is not included.http://docs.oracle.com/javaee/6/tutorial/doc/gkkqg.html

Root Cause

  • The property jnp.timeout is only to set the timeout for the lookup or invocation of a remote method, also this property is not supported in EAP6 is is from former versions. The execution is not controlled by that timeout.

  • It can be not handled within the enterprise application code because it is not allowed to handle/start Threads in an enterprise application, this is the responsibility of the container.

Components
Category

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.