Spring [SOLVED]: Spring Boot not connecting to RabbitMQ

Spring [SOLVED]: Spring Boot not connecting to RabbitMQ

Home Forums Frameworks Spring Spring [SOLVED]: Spring Boot not connecting to RabbitMQ

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #243819

    Cloudy Point
    Keymaster

    QuestionQuestion

    Update: Posted the non-working version on https://github.com/justsomecoder/boot-rabbit-issue

    I am trying to implement some basic RabbitMQ sending and receiving functionality but cannot seem to get it working across both my Spring Boot projects. While I have tried multiple examples, as of now I implemented the example at https://spring.io/guides/gs/messaging-rabbitmq/, with the only exception that I defined the beans in the Application.java in a separate RabbitConfig class annotated with @Configuration.

    I also tried it the exact way it’s done in the example, however this also does not work.

    The funny thing is, the implementation works in one (older) Spring Boot project while it’s not working in a newer Boot project. In the other project the output during runtime shows me that the connection to RabbitMQ is succesfully setup:

    Part of output working project

    2017-12-18 10:53:45,205 INFO [restartedMain] o.s.j.e.a.AnnotationMBeanExporter [MBeanExporter.java:431] Registering beans for JMX exposure on startup
    2017-12-18 10:53:45,215 INFO [restartedMain] o.s.j.e.a.AnnotationMBeanExporter [MBeanExporter.java:916] Bean with name 'rabbitConnectionFactory' has been autodetected for JMX exposure
    2017-12-18 10:53:45,219 INFO [restartedMain] o.s.j.e.a.AnnotationMBeanExporter [MBeanExporter.java:678] Located managed bean 'rabbitConnectionFactory': registering with JMX server as MBean [org.springframework.amqp.rabbit.connection:name=rabbitConnectionFactory,type=CachingConnectionFactory]
    2017-12-18 10:53:45,238 INFO [restartedMain] o.s.c.s.DefaultLifecycleProcessor [DefaultLifecycleProcessor.java:343] Starting beans in phase -2147482648
    2017-12-18 10:53:45,239 INFO [restartedMain] o.s.c.s.DefaultLifecycleProcessor [DefaultLifecycleProcessor.java:343] Starting beans in phase 2147483647
    2017-12-18 10:53:45,268 INFO [container-1] o.s.a.r.c.CachingConnectionFactory [AbstractConnectionFactory.java:359] Created new connection: SimpleConnection@6bb6caa0 [delegate=amqp://guest@127.0.0.1:32770/, localPort= 51889]
    2017-12-18 10:53:45,273 INFO [container-1] o.s.a.r.c.RabbitAdmin [RabbitAdmin.java:491] Auto-declaring a non-durable, auto-delete, or exclusive Queue (floors) durable:false, auto-delete:false, exclusive:false. It will be redeclared if the broker stops and is restarted while the connection factory is alive, but all messages will be lost.
    

    Output non-working project

    2017-12-18 18:40:39.452  INFO 4722 --- [  restartedMain] name.nameFootstepProcessor   : Starting nameFootstepProcessor on Macbook-Pro-van-Lars.local with PID 4722 (/Users/lars/IdeaProjects/name-footstep-processor/target/classes started by lars in /Users/lars/IdeaProjects/name-footstep-processor)
    2017-12-18 18:40:39.453  INFO 4722 --- [  restartedMain] name.nameFootstepProcessor   : No active profile set, falling back to default profiles: default
    2017-12-18 18:40:39.453 DEBUG 4722 --- [  restartedMain] o.s.boot.SpringApplication               : Loading source class name.nameFootstepProcessor
    2017-12-18 18:40:39.945  INFO 4722 --- [  restartedMain] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@426b0d00: startup date [Mon Dec 18 18:40:39 CET 2017]; root of context hierarchy
    2017-12-18 18:40:40.697  INFO 4722 --- [  restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
    2017-12-18 18:40:41.389  INFO 4722 --- [  restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.amqp.rabbit.annotation.RabbitBootstrapConfiguration' of type [org.springframework.amqp.rabbit.annotation.RabbitBootstrapConfiguration$$EnhancerBySpringCGLIB$$b410db6c] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
    

    It also shows up as a consumer for the queue in the RabbitMQ Admin Management interface.

    In my other project, none of this is shown. However, in both projects the Rabbit configuration class is found and the beans are loaded (checked using Print all the Spring beans that are loaded – Spring Boot).

    Both projects share the same dependency ‘spring-boot-starter-amqp’. They also both share the same application.properties file containing the right information for connecting to my local RabbitMQ server. Is there anything I can do to find out why one project is loading the Rabbit
    configuration beans correctly while the other is not?

    Below I have attached some files which I think are helpful to understand the problem more, but if any other files or output are needed please let me know. I changed some package names
    for privacy concerns.

    Thank you!

    Regards,
    larsl95.

    Working project
    Spring Boot 1.5.3

    Non-working project
    Spring Boot 1.5.9

    application.properties (same for both projects, port is due to Docker, mapped to 5276)

    spring.rabbitmq.host=localhost
    spring.rabbitmq.port=32770
    spring.rabbitmq.username=guest
    spring.rabbitmq.password=guest
    

    RabbitConfig.java (same for both projects)

    package name.configuration;
    
    import org.springframework.context.ConfigurableApplicationContext;
    import name.queue.Receiver;
    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.Queue;
    import org.springframework.amqp.core.TopicExchange;
    import org.springframework.amqp.rabbit.connection.ConnectionFactory;
    import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
    import org.springframework.amqp.rabbit.listener.adapter.MessageListenerAdapter;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.stereotype.Component;
    
    import java.util.Arrays;
    
    @Component
    @Configuration
    public class RabbitConfig {
    
        public final static String queueName = "floors";
    
        public RabbitConfig(ConfigurableApplicationContext ctx) {
            this.printBeans(ctx);
        }
    
        @Bean
        Queue queue() {
            return new Queue(queueName, false);
        }
    
        @Bean
        TopicExchange exchange() {
            return new TopicExchange("test-exchange");
        }
    
        @Bean
        Binding binding(Queue queue, TopicExchange exchange) {
            return BindingBuilder.bind(queue).to(exchange).with(queueName);
        }
    
        @Bean
        SimpleMessageListenerContainer container(ConnectionFactory connectionFactory,
                                                 MessageListenerAdapter listenerAdapter) {
            SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
            container.setConnectionFactory(connectionFactory);
            container.setQueueNames(queueName);
            container.setMessageListener(listenerAdapter);
            return container;
        }
    
        @Bean
        MessageListenerAdapter listenerAdapter(Receiver receiver) {
            return new MessageListenerAdapter(receiver, "receiveMessage");
        }
    
        // just added this to know which beans are loaded, called it from constructor to see
        // if RabbitConfig class is found by Spring at all
        private void printBeans(ConfigurableApplicationContext ctx) {
            String[] beanNames = ctx.getBeanDefinitionNames();
            Arrays.sort(beanNames);
            for (String beanName : beanNames) {
                System.out.println(beanName);
            }
        }
    
    }
    

    Receiver.java (same for both projects)

    package name.queue;
    
    import org.springframework.stereotype.Component;
    
    import java.util.concurrent.CountDownLatch;
    
    @Component
    public class Receiver {
    
        private CountDownLatch latch = new CountDownLatch(1);
    
        public void receiveMessage(String message) {
            System.out.println("Received <" + message + ">");
            latch.countDown();
        }
    
        public CountDownLatch getLatch() {
            return latch;
        }
    }
    

    Main.java (non-working project)

    @SpringBootApplication
    public class Main {
    
        public static void main(String[] args) {
            SpringApplication app = new SpringApplication(Main.class);
            app.setWebEnvironment(false);
            ConfigurableApplicationContext appContext = app.run(args);
            name.tcp.TcpServer tcpServer = new name.tcp.TcpServer();
        }
    
    }
    

    Main.java (working project)

    package name;
    
    import name.tcp.TcpServer;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.support.SpringBootServletInitializer;
    import org.springframework.context.ConfigurableApplicationContext;
    
    import java.io.IOException;
    
    @SpringBootApplication
    public class Main extends SpringBootServletInitializer {
    
        public static void main(String[] args) {
            ConfigurableApplicationContext app = SpringApplication.run(Main.class, args);
            TcpServer tcpServer = new TcpServer();
            System.out.println("starting TCP server from main");
        }
    
    }
    

    Runner.java (same for both projects)

    package name.queue;
    
    import java.util.concurrent.TimeUnit;
    
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.CommandLineRunner;
    import org.springframework.context.ConfigurableApplicationContext;
    import org.springframework.stereotype.Component;
    import name.configuration.RabbitConfig;
    
    @Component
    public class Runner implements CommandLineRunner {
    
        private final RabbitTemplate rabbitTemplate;
    
        @Autowired
        public Runner(RabbitTemplate rabbitTemplate) {
            this.rabbitTemplate = rabbitTemplate;
        }
    
        @Override
        public void run(String... args) throws Exception {
            System.out.println("Sending message...");
            rabbitTemplate.convertAndSend(RabbitConfig.queueName, "Hello from RabbitMQ!");
        }
    
    }
    

    #243820

    Cloudy Point
    Keymaster

    Accepted AnswerAnswer

    Seeing the project you linked that reproduced the issue, when the application is started, the TcpServer component gets initialized, which causes the startListen() method to be executed.

    That method has an infinite loop without any separate thread being created, hence blocking the remaining of the startup process (code excerpt below).

    public void startListen() throws IOException {
        while (true) {
            Socket clientSocket = serverSocket.accept();
            threadPool.submit(new XClientHandler(clientSocket,eventProducer));
        }
    }
    

    Removing that component shows that the RabbitMQ listener gets started, so I would just advise to (at least) use a different Thread for your TcpServer.

    Source: https://stackoverflow.com/questions/47873835/spring-boot-not-connecting-to-rabbitmq
    Author: Tome
    Creative Commons License
    This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.