javaguy
javaguy

Reputation: 1133

Message Driven Beans and Retry with exponential back off

I have a requirement where in if service (Restful service) I call from message driven bean is down or does not return success, I need to rollBack message back to queue, wait for some time(exponentially) and then read message again from queue and try connecting to service.

What I am trying:

Within the OnMessage method, in case I receive an exception from the service which is calling the Restful service, I am rolling back using messageDrivenContext.setRollBackOnly() and I can do something like Thread.sleep(RETRY_WAIT_TIME);

But how do I make sure that RETRY_WAIT_TIME is increased exponentially?

Probably I need to maintain state of the bean, but can anyone please suggest how I can do that?

Upvotes: 1

Views: 719

Answers (1)

Filip
Filip

Reputation: 877

There are multiple ways to achieve this, depending on your setup. If all messages will invoke the same service you can define a global throttling parameter in your MDB context which defines the time to let the MDB sleep. You can use a rudimentary exponential delay as following for example:

final int throttleTime = 60;  //Assume we delay 60 sec before retry
int throttle = 1;

private int getThrottle(){
  throttle = throttleTime * throttle;
  return throttle;
}

private void resetThrottle(){
  throttle = 1;
}

public void onMessage(Message message){
  try{
     service.invoke();
  } catch (InvocationException e) {
    try{
      Thread.sleep(getThrottle()*1000);
      onMessage(message);
    } catch (InterruptedException e) {
      logger.error(e.getMessage());
    }
  } finally {    
    resetThrottle();
  }
}       

Note that some application servers already gradually augment the retry time for reading messages when the MDB throws back exceptions to the container. Likewise some queuing systems allow configurations to let messages appear at a certain time in the queue. Check what the specs of your infrastructure describe on that topic.

Upvotes: 1

Related Questions