如果无法处理消息,例如由于某些外部端点故障,我需要重新传递消息。所以我正在使用以下 MDB 配置(值得一提的是,我正在使用 openMQ (Glassfish 4.1)):
@MessageDriven(mappedName = "MyQueue", name = "MyQueue", activationConfig = {
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryAttempts", propertyValue = "10"),
@ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryInterval", propertyValue = "30000")})
这是 onMessage() 方法:
@Override
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void onMessage (Message message)
{
try
{
//some processing here
}
catch (JMSException jmsException)
{
logger.log (Level.SEVERE, "Exception processing notification message", jmsException);
}
catch (BackingStoreException e)
{
// because of throwing RuntimeException, the message is going to be redelivered according to mdb configuration params(interval and attempts count)
throw new RuntimeException ();
}
}
为了重新传递消息,也可以回滚事务,但是 openMQ 缺少重新传递间隔的属性,所以它不适合我:
https://github.com/javaee/openmq/issues/220
https://github.com/javaee/openmq/issues/23
https://github.com/javaee/openmq/issues/134
总而言之,重新传递工作正常,除了一个时刻:如果要重新传递消息,mdb 不会释放连接并为 endpointExceptionRedeliveryInterval * endpointExceptionRedeliveryAttempts 保留它,在我的例子中是 5 分钟。因此,maxPoolSize 的默认值为 32,32 条“坏”消息足以阻止 mdb。
有没有办法在消息重新传递的情况下释放连接?