Hello!

To illustrate the missing feature, assume we have the following route:
from(activemq:queue:foo)
  .to("cxf:bean:orderService")
  .to("activemq:queue:bar");

Our orderService is out of order every day for 30 min - 60 min. In this
time, we cannot process messages from the foo queue. We have to delay the
processing until the orderService returns to operate normal. We have
multiple possibilities at present to handle the requirement, but all have
some drawbacks, IMO.

1) Make the route transacted and let the ActiveMQ Broker do the (redelivery)
work.
from(activemq:queue:foo)
  .transacted("REQUIRED")
  .to("cxf:bean:orderService")
  .to("activemq:queue:bar");

Drawbacks:
- We are not the owner of this configuration cannot ensure the ActiveMQ
broker/JMSConnectionFactory is configured properly for the redelivery.
- We cannot use different redelivery policies for different routes.


2) Use the Camel dead letter error handler to catch the errors and do the
redelivery.
errorHandler(
  deadLetterChannel(activemq:queue:foo.DLQ)
  .maximumRedeliveries(8)
  .deliveryDelay(60000)
  .useExponentialBackOff()
  .backOffMultiplier(2));

from(activemq:queue:foo)
  .to("cxf:bean:orderService")
  .to("activemq:queue:bar");

Drawbacks:
- When we are in the seventh redelivery, we will wait over one hour for the
next redelivery. If we have to shout down our container (which is
ServiceMix), it will take over one hour or we have to force the shutdown and
we loose the message.


To solve the missing feature, we have at least two options:


a) Provide a "special" error handler which uses the "delay and schedule
message delivery" feature from ActiveMQ [3]. This error handler should/could
looks like the RedeliveryErrorHandler:
errorHandler(
  activeMqDeadLetterChannel(activemq:queue:foo.DLQ)
  .maximumRedeliveries(8)
  .deliveryDelay(60000)
  .useExponentialBackOff()
  .backOffMultiplier(2));

from(activemq:queue:foo)
  .to("cxf:bean:orderService")
  .to("activemq:queue:bar");

If an error occurs, this error handler should evaluate the (JMS) headers
whether or not the message should redelivered, which delay should be used,
update the (JMS) headers with the new values and enqueue the message again
into the queue the message was read from. May be this route must/should also
be transacted to make sure we do not loose messages.


b) Add the options described in [1] and [2] to the activemq component to
allow the user to specify the redelivery behavior per endpoint definition:
from(activemq:queue:foo?maximumRedeliveries=10&deliveryDelay=60000&useExponentialBackOff=true&backOffMultiplier=2)
  .transacted("REQUIRED")
  .to("cxf:bean:orderService")
  .to("activemq:queue:bar");

This options should be used to configure the JMSConnection.
I know it's also possible to configure this in the
ActiveMQConnectionFactory, but:
- We are not the "owner" of this configuration. We use an OSGI lookup to get
the reference to the exported ActiveMQConnectionFactory.
- It's a global configuration and we may need the possibility to override
some options (deliveryDelay) for other routes.


Do I miss something? What are your thoughts?


[1] http://activemq.apache.org/redelivery-policy.html
[2] http://activemq.apache.org/message-redelivery-and-dlq-handling.html
[3] http://activemq.apache.org/delay-and-schedule-message-delivery.html

Looking forward for many opinions :-),
Christian

Reply via email to