0
votes

I'm developing a consumer application using Spring AMQP that receives messages from RabbitMQ. There is a topic exchange declared. To connect to Rabbit I create a queue with an empty name, because the broker will provide an automatic queue name, see the InterCor M4 Upgraded Specifications Hybrid specifications:

@Bean
public TopicExchange exchange() {
    TopicExchange topicExchange = new TopicExchange(topicExchangeName);
    topicExchange.setShouldDeclare(false);
    return topicExchange;
}

@Bean
public Queue queue() {
  return new Queue("", queueDurable, queueExclusive, queueAutoDelete, queueParameters);
}

@Bean
public Binding binding(Queue queue, TopicExchange exchange) {
    return BindingBuilder.bind(queue).to(exchange).with(routingKey);
}

But when I try to configure an AMQP Inbound Channel Adapter using the Spring Integration Java DSL:

@Autowired
private Queue queue;

@Bean
public IntegrationFlow amqpInbound(ConnectionFactory connectionFactory) {
  return IntegrationFlows.from(Amqp.inboundAdapter(connectionFactory, queue))
      .handle(m -> System.out.println(m.getPayload()))
      .get();
}

I get an error 'queueName' cannot be null or empty

2018-05-25 13:39:15.080 ERROR 14636 --- [erContainer#0-1] o.s.a.r.l.SimpleMessageListenerContainer : Failed to check/redeclare auto-delete queue(s).

java.lang.IllegalArgumentException: 'queueName' cannot be null or empty
    at org.springframework.util.Assert.hasText(Assert.java:276) ~[spring-core-5.0.6.RELEASE.jar:5.0.6.RELEASE]
    at org.springframework.amqp.rabbit.core.RabbitAdmin.getQueueProperties(RabbitAdmin.java:337) ~[spring-rabbit-2.0.3.RELEASE.jar:2.0.3.RELEASE]
    at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.redeclareElementsIfNecessary(AbstractMessageListenerContainer.java:1604) ~[spring-rabbit-2.0.3.RELEASE.jar:2.0.3.RELEASE]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:963) [spring-rabbit-2.0.3.RELEASE.jar:2.0.3.RELEASE]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_162]

How can I set a value of the message queue name to an empty string?

2

2 Answers

6
votes

That is not a good solution.

The problem is that with a broker-generated queue name, if the connection is lost and re-established, the queue name will change, but the container won't know about the new queue and will try to consume from the old one.

AnonymousQueue solves this problem by the framework generating the random name.

But, anonymous queues are not durable, are exclusive and are auto-delete.

If you want a Queue with different properties to that, but still want a random name, use

@Bean
public Queue queue() {
  return new Queue(new AnonymousQueue.Base64UrlNamingStrategy().generateName(),
      queueDurable, queueExclusive, queueAutoDelete, queueParameters);
}

That way, if the connection is lost and re-established, the queue will get the same name.

2
votes

The AMQP-816 issue has been fixed and now is available in Spring Boot 2.1.0.

Updating the parent of the project fixes the issue:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.0.RELEASE</version>
</parent>

Empty queue name

spring:
    rabbitmq:
        queue:
            name:
            durable: false
            exclusive: true
            autoDelete: true

creates an automatic queue name amq.gen-U1vKiSfIvy8bO11jLD29Sw:

Empty queue name

Non-empty queue name

spring:
    rabbitmq:
        queue:
            name: abc
            durable: false
            exclusive: true
            autoDelete: true

creates a queue named abc:

Non-empty queue name