raven-king
raven-king

Reputation: 1550

Camel RabbitMQ endpoint cannot be created when a dead letter exchange is declared

I'm having an issue creating a RabbitMQ endpoint with Camel. The issue only occurs when I declare a a dead message letter exchange option based on the camel documentation. This is my URN for creating the endpoint:

rabbitmq://localhost/com.mydomain.inbound.exhange?deadLetterExchange=dead.msgs

All is fine when I omit the deadLetterExchange option but as soon as I include it I get the following (not very helpful) exception:

Caused by: java.lang.NullPointerException at com.rabbitmq.client.impl.ChannelN.validateQueueNameLength(ChannelN.java:1244) ~[amqp-client-3.6.1.jar:?] at com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:843) ~[amqp-client-3.6.1.jar:?] at com.rabbitmq.client.impl.ChannelN.queueDeclare(ChannelN.java:61) ~[amqp-client-3.6.1.jar:?] at org.apache.camel.component.rabbitmq.RabbitMQDeclareSupport.declareAndBindQueue(RabbitMQDeclareSupport.java:96) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.component.rabbitmq.RabbitMQDeclareSupport.declareAndBindDeadLetterExchangeWithQueue(RabbitMQDeclareSupport.java:43) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.component.rabbitmq.RabbitMQDeclareSupport.declareAndBindExchangesAndQueuesUsing(RabbitMQDeclareSupport.java:35) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.component.rabbitmq.RabbitMQEndpoint.declareExchangeAndQueue(RabbitMQEndpoint.java:222) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.component.rabbitmq.RabbitConsumer.openChannel(RabbitConsumer.java:288) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.component.rabbitmq.RabbitConsumer.(RabbitConsumer.java:57) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.component.rabbitmq.RabbitMQConsumer.createConsumer(RabbitMQConsumer.java:108) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.component.rabbitmq.RabbitMQConsumer.startConsumers(RabbitMQConsumer.java:90) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.component.rabbitmq.RabbitMQConsumer.doStart(RabbitMQConsumer.java:160) ~[camel-rabbitmq-2.17.0.jar:2.17.0] at org.apache.camel.support.ServiceSupport.start(ServiceSupport.java:61) ~[camel-core-2.17.0.jar:2.17.0] at org.apache.camel.impl.DefaultCamelContext.startService(DefaultCamelContext.java:3269) ~[camel-core-2.17.0.jar:2.17.0] at org.apache.camel.impl.DefaultCamelContext.doStartOrResumeRouteConsumers(DefaultCamelContext.java:3563) ~[camel-core-2.17.0.jar:2.17.0] at org.apache.camel.impl.DefaultCamelContext.doStartRouteConsumers ....

Just no note that I've also tried creating the exchange and queue manually in a hope that this may work but no luck.

Additional Info:

Upvotes: 1

Views: 2313

Answers (1)

KapudanPasha
KapudanPasha

Reputation: 154

Try adding a deadLetterQueueoption -

rabbitmq://localhost/com.mydomain.inbound.exhange?deadLetterExchange=dead.msgs&deadLetterQueue=my.dead.letter.queue

I also had to add further options to the uri to get it to work. I added

  • deadLetterExchangeType
  • queueArgsConfigurer

The queueArgsConfigurer is an implementation of org.apache.camel.component.rabbitmq.ArgsConfigurer

class MyQueueArgs implements ArgsConfigurer {

    void configurArgs(Map<String, Object> args) { //misspelling!!
        args.put("x-dead-letter-exchange", "my.dead.letter")
        args.put("x-dead-letter-routing-key", "my.dead.letter.key")
    }

}

Mine is a Spring app so myArgs (see below) is created in the bean factory.

So, the full uri is like this -

rabbitmq://hostname/exchangeName?routingKey=$routingKey&vhost=virtualHostname&exchangeType=exType&autoDelete=false&queue=my.queue&deadLetterExchange=my.dead.letter&deadLetterExchangeType=dlExType&deadLetterQueue=my.dead.letter.queue&queueArgsConfigurer=#myArgs

I probably don't need to specify the dead letter exchange in the uri and the ArgsConfigurer implementation.

For more on ArgsConfigurer this Camel issue might help - #8457

I had to look at the source code to figure a lot of this out. What is missing from the doc is a definition of dependencies. There are some options, particularly around dead letter exchanges, which become mandatory if another is specified. That's why you are getting your errors. Have a look at populateQueueArgumentsFromDeadLetterExchange in RabbitMQDeclareSupport.

EDIT

A simplification to my answer - I dropped the ArgsConfigurer implementation in the end. I went with this -

rabbitmq://myHostname/myExchangeName? username=myUserName& password=myPassword& queue=myQueueName& routingKey=myRoutingKey& vhost=myVirtualHostname& exchangeType=topic& autoDelete=false& deadLetterExchange=myDeadLetter& deadLetterExchangeType=topic& deadLetterQueue=myDeadLetterQueue& deadLetterRoutingKey=myDeadLetterRoutingKey& autoAck=false

Upvotes: 1

Related Questions