5

It would be useful to be able to identify the RabbitMQ client by its connection name.

I'm using Spring Cloud Streams abstraction and with default settings I getting something like that:

enter image description here

How can I set a custom RabbitMQ connection name in my Spring Boot client?


EDIT

Spring Boot 1.7+

This is solution based on Gary Russell's answer:

@Configuration
public class MessagingConfiguration {
    private final String instanceId = UUID.randomUUID().toString().substring(0, 8); // TODO: Environment/Consul/Eureka
    private final String connectionNamePrefix;
    private AtomicInteger connectionNumber = new AtomicInteger(0);

    public MessagingConfiguration(@Value("${custom.rabbitmq.connection-name-prefix:SpringBootApp}") String connectionNamePrefix) {
        this.connectionNamePrefix = connectionNamePrefix;
    }

    private String generateConnectionName() {
        return connectionNamePrefix + '#' + instanceId + ':' +  connectionNumber.getAndIncrement();
    }

    @Bean
    public SmartInitializingSingleton reconfigureConnectionFactory(final AbstractConnectionFactory cf) {
        return () -> cf.setConnectionNameStrategy(f -> generateConnectionName());
    }
}

It works with the default configuration, but doesn't work for a multiple systems connection.

Spring Boot 2.0.1+

@Configuration
public class MessagingConfiguration {
    private final String instanceId = UUID.randomUUID().toString().substring(0, 8); // TODO: Environment/Consul/Eureka
    private final String connectionNamePrefix;
    private AtomicInteger connectionNumber = new AtomicInteger(0);

    public MessagingConfiguration(@Value("${custom.rabbitmq.connection-name-prefix:SpringBootApp}") String connectionNamePrefix) {
        this.connectionNamePrefix = connectionNamePrefix;
    }

    private String generateConnectionName() {
        return connectionNamePrefix + '#' + instanceId + ':' +  connectionNumber.getAndIncrement();
    }

    @Bean
    public ConnectionNameStrategy defineConnectionNameStrategy() {
        return connectionFactory -> generateConnectionName();
    }
}

Note, there is a bug in a multi-binder scenario.

Community
  • 1
  • 1
kinjelom
  • 6,105
  • 3
  • 35
  • 61

1 Answers1

5

Starting with version 2.0 1.7 (see the documentation) you can provide a ConnectionNameStrategy...

@Bean
public CachingConnectionFactory connectionFactory() {
    CachingConnectionFactory cf = new CachingConnectionFactory("localhost");
    cf.setConnectionNameStrategy(f -> "myConnectionName");
    return cf;
}

enter image description here

EDIT

The strategy can be set any time before the connection is opened. If, say, you want to use Spring Boot's auto configured factory (which is used by Spring Cloud Stream by default), you could do something like this...

@Bean
public SmartInitializingSingleton reconfigureCf(final CachingConnectionFactory cf) {
    return () -> cf.setConnectionNameStrategy(f -> "myName");
}

This will be run before anything is start()ed.

Actually it was backported to 1.7.x.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Thanks, but in this way I must create own ConnectionFactory, configure it etc. I just want to inject my ConnectionNameStrategy, nothing more. Is there any way to do it? – kinjelom Mar 03 '18 at 23:01
  • Thank you for the magic :) It works with [default configuration](https://github.com/wildloop/streams-demo/blob/master/src/main/resources/application-1vh.yml), but doesn't work when I use [connection to multiple systems](https://github.com/wildloop/streams-demo/blob/master/src/main/resources/application-2vh.yml). Is there any chance to add autoconfiguration support for something like this property: `spring.rabbitmq.connection-name-prefix`? – kinjelom Mar 04 '18 at 15:17
  • That requires a change to boot since each of those binders gets loaded into a separate application context. I have [issued a pull request against boot](https://github.com/spring-projects/spring-boot/pull/12339) if you want to track it. – Gary Russell Mar 04 '18 at 17:53
  • BTW, it looks like [multiple-systems configuration](https://github.com/wildloop/streams-demo/blob/master/src/main/resources/application-2vh.yml) always inherit default environment with `Spring Boot 2.0` and and `Spring Cloud Finchley.M8`. It works OK with `Spring Boot 1.5.9` and `Spring Cloud Edgware.SR2` on same configuration. Where should I post this issue? – kinjelom Mar 04 '18 at 20:33
  • I would start with stream. An example the exhibits the behavior will help. – Gary Russell Mar 04 '18 at 21:03
  • A custom `ConnectionNameStrategy` is ignored if there is a custom binder configuration: https://github.com/spring-cloud/spring-cloud-stream/issues/1541 – kinjelom Nov 27 '18 at 00:00