1

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?

Tiny
  • 27,221
  • 105
  • 339
  • 599
javaguy
  • 927
  • 2
  • 16
  • 37
  • 1
    I would first investigate the configuration options of whatever message queue you're using to see if it doesn't have such specific redelivery settings. I would make your life easy and not demand that the interval is exponential. If you deviate from the standards you're going into the territory of rolling your own and not using an MDB, but rather a manual built message client. – Gimby Jan 19 '16 at 13:58
  • 1
    Using `Thread.sleep()` in a Java EE environment is a kind of red-herring and seriously forbidden by the specification. – Tiny Jan 20 '16 at 20:18

1 Answers1

1

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.

Filip
  • 857
  • 8
  • 19
  • Thanks Filip for your response.Yes ,in my case, all messages will invoke the same service and I have configured 10 instances of MDB in websphere.Could you please let me know where to set Global throttling parameter and how I can achieve exponential delay... – javaguy Jan 19 '16 at 14:49