Thread.sleep() in an EJB

EJB 3.1 brought a new @Asynchronous feature that you can take advantage of:

@Asynchronous
@TransactionAttribute(NOT_SUPPORTED)
public Future<WebServiceResult> callWebService(int retries) {
    WebServiceResult result = webService.call();

    if (!result.equals(BUSY)) {
        return result;
    }

    if (retries <= 0) {
        throw new TooBusyException();
    }

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }

    return callWebService(retries - 1);
}

Then simply call you web service with:

Future<WebServiceResult> result = yourEJB.callWebService(1);

// Can do some interesting stuff here.
// ...
// ...

result.get(2, SECONDS);  // Block for up to 2 seconds.

As you can see you get configurable number of retries and timeout for free.

How does this differ from just calling Thread.sleep()? Returning Future is more explicit and manageable. Also I don't think Thread.sleep() is that harmful. The only problem is that this EJB instance can now longer be reused by other clients. With Future asynchronous invocation happens inside some other EJB and thread pool. As to importance of Thread#interrupt() inside the catch block, refer Why invoke Thread.currentThread.interrupt() when catch any InterruptException?

Another idea: use aspect around calling web service, catch BusyException once and retry.


In the EJB restrictions FAQ it specifically states that you

should not create or manage threads

And putting a thread to sleep counts as "managing" it.

In your case, when the web service returns a "busy" status, you could schedule a job to retry sending the message at a later point in time, for instance by using the Quartz Scheduler. The execution would end there, and any further processing should be delegated to the job scheduler.

Tags:

Jakarta Ee

Ejb