问题
I am using
Spring Integration 4.1.2.RELEASE
Spring AMQP 1.4.3.RELEASE
When an exception is thrown, I am expecting the message to be requeued. I believe that I have all the conditions met for this as I gleaned from this post
In the post, I learned that there are three conditions to ensure a requeue:
1) The acknowledge-mode
must be AUTO.
2) The requeue-rejected
must be TRUE.
3) Throw any exception BUT AmqpRejectAndDontRequeueException
.
I believe I am meeting these conditions in some test code that I wrote:
Configuration
The service activator is where an exception is thrown that does not inherit from AmqpRejectAndDontRequeueException
@Autowired
public void setSpringIntegrationConfigHelper (SpringIntegrationHelper springIntegrationConfig) {
this.springIntegrationConfigHelper = springIntegrationConfig;
}
@Bean
public String priorityPOCQueueName() {
return "poc.priority";
}
@Bean
public Queue priorityPOCQueue(RabbitAdmin rabbitAdmin) {
Queue queue = new Queue(priorityPOCQueueName(), true);
rabbitAdmin.declareQueue(queue);
return queue;
}
@Bean
public Binding priorityPOCQueueBinding(RabbitAdmin rabbitAdmin) {
Binding binding = new Binding(priorityPOCQueueName(),
DestinationType.QUEUE,
"amq.direct",
priorityPOCQueue(rabbitAdmin).getName(),
null);
rabbitAdmin.declareBinding(binding);
return binding;
}
@Bean
public AmqpTemplate priorityPOCMessageTemplate(ConnectionFactory amqpConnectionFactory,
@Qualifier("priorityPOCQueueName") String queueName,
@Qualifier("jsonMessageConverter") MessageConverter messageConverter) {
RabbitTemplate template = new RabbitTemplate(amqpConnectionFactory);
template.setChannelTransacted(false);
template.setExchange("amq.direct");
template.setQueue(queueName);
template.setRoutingKey(queueName);
template.setMessageConverter(messageConverter);
return template;
}
@Autowired
@Qualifier("priorityPOCQueue")
public void setPriorityPOCQueue(Queue priorityPOCQueue) {
this.priorityPOCQueue = priorityPOCQueue;
}
@Bean(name="exec.priorityPOC")
TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor e = new ThreadPoolTaskExecutor();
e.setCorePoolSize(1);
e.setQueueCapacity(1);
return e;
}
@Bean(name="poc.priorityChannel")
public MessageChannel pocPriorityChannel() {
PriorityChannel c = new PriorityChannel(new PriorityComparator());
c.setComponentName("poc.priorityChannel");
c.setBeanName("poc.priorityChannel");
return c;
}
@Bean(name="poc.inboundChannelAdapter") //make this a unique name
public AmqpInboundChannelAdapter amqpInboundChannelAdapter(@Qualifier("exec.priorityPOC") TaskExecutor taskExecutor
, @Qualifier("poc.errorChannel") MessageChannel pocErrorChannel) {
int concurrentConsumers = 1;
AmqpInboundChannelAdapter a = mimediaSpringIntegrationConfigHelper.createInboundChannelAdapter(taskExecutor
, pocPriorityChannel(), new Queue[]{priorityPOCQueue}, concurrentConsumers);
a.setErrorChannel(pocErrorChannel);
return a;
}
@ServiceActivator(inputChannel="poc.priorityChannel")
public void processUserFileCollectionAudit(@Header(SimulateErrorHeaderPostProcessor.ERROR_SIMULATE_HEADER_KEY) Boolean simulateError, PriorityMessage priorityMessage) throws InterruptedException {
if (isFirstMessageReceived == false) {
Thread.sleep(15000); //Cause a bit of a backup so we can see prioritizing in action.
isFirstMessageReceived = true;
}
logger.debug("Received message with priority: " + priorityMessage.getPriority() + ", simulateError: " + simulateError + ", Current retry count is "
+ priorityMessage.getRetryCount());
if (simulateError && priorityMessage.getRetryCount() < PriorityMessage.MAX_MESSAGE_RETRY_COUNT) {
logger.debug(" Simulating an error and re-queue'ng. Current retry count is " + priorityMessage.getRetryCount());
priorityMessage.setRetryCount(priorityMessage.getRetryCount() + 1);
throw new NonAdequateResourceException();
} else if (simulateError && priorityMessage.getRetryCount() >= PriorityMessage.MAX_MESSAGE_RETRY_COUNT) {
logger.debug(" Max retry count exceeded");
}
}
SpringIntegrationHelper
This is where auto acknowledge and requeue rejected are being set.
protected ConnectionFactory connectionFactory;
protected MessageChannel errorChannel;
protected MessageConverter messageConverter;
@Autowired
public void setConnectionFactory (ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
@Autowired
public void setErrorChannel(MessageChannel errorChannel) {
this.errorChannel = errorChannel;
}
@Autowired
public void setMessageConverter(@Qualifier("jsonMessageConverter") MessageConverter messageConverter) {
this.messageConverter = messageConverter;
}
public AmqpInboundChannelAdapter createInboundChannelAdapter(TaskExecutor taskExecutor
, MessageChannel outputChannel, Queue[] queues, int concurrentConsumers) {
SimpleMessageListenerContainer listenerContainer =
new SimpleMessageListenerContainer(connectionFactory);
//AUTO is default, but setting it anyhow.
listenerContainer.setAcknowledgeMode(AcknowledgeMode.AUTO);
listenerContainer.setAutoStartup(true);
listenerContainer.setConcurrentConsumers(concurrentConsumers);
listenerContainer.setMessageConverter(messageConverter);
listenerContainer.setQueues(queues);
//listenerContainer.setChannelTransacted(false);
listenerContainer.setPrefetchCount(100);
listenerContainer.setTaskExecutor(taskExecutor);
listenerContainer.setDefaultRequeueRejected(true);
AmqpInboundChannelAdapter a = new AmqpInboundChannelAdapter(listenerContainer);
a.setMessageConverter(messageConverter);
a.setAutoStartup(true);
//TODO This was stopping my custom error handler. Fix. a.setErrorChannel(errorChannel);
a.setHeaderMapper(MimediaAmqpHeaderMapper.createPassAllHeaders());
a.setOutputChannel(outputChannel);
return a;
}
Why are my messages not being re-queued?
回答1:
4) The exception has to be thrown on the listener's thread.
It will only work if the exception is thrown on the listener container thread that received the message.
Since you are using a PriorityChannel
as the output channel of the adapter, you are immediately handing the message off to another thread so there is no exception on the listener thread and the message is always ack'd.
来源:https://stackoverflow.com/questions/32612175/messages-are-not-requeue-ing-on-thrown-exception