Home > Software design >  Trying start RabbitListener on command after builded Application - RabbitListenerEndpointRegistry is
Trying start RabbitListener on command after builded Application - RabbitListenerEndpointRegistry is

Time:01-26

I searched all over the stackOverFlow and couldn't find an answer.

I need to start RabbitListener on command - from just REST send request to start this listener (no other option).

So I found that I need set properties in Listener like that: @RabbitListener(queues = "myQueue", id = "listener_id", autoStartup = "false") (of course is albo annotation @Component).

I made also initializer class using implementation of ApplicationContextAware and RabbitListenerEndpointRegistry like below:

@Slf4j
 @Component
public class ListenerInitializer implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public void startListener() {
        RabbitListenerEndpointRegistry listenerRegistry = applicationContext.getBean(RabbitListenerEndpointRegistry.class);
        listenerRegistry.getListenerContainer("listener_id").start();
        log.info("Listener started.");
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

And when I tried to use method startListener() mostly I received NullPointerException: null like RabbitListenerEndpointRegistry doesn't exist. I wrote mostly, because sometimes (every time I make mvn clean install) it works and everything is fine. But mostly I received NullPointerException.

With @Autowired of ApplicationContext same situation.

I tried with: @Autowired RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry but in that case shows me that RabbitListenerEndpointRegistry bean doesn't exist (also through @RequiedArgsConstructor.

I tried also to make configuration like below:

@Configuration
@EnableRabbit
class ListenerConfig {

    @Bean
    @DependsOn("listener")
    ListenerInitializer ListenerInitializer() {
        return new ListenerInitializer();
    }

    @Bean(name = "listener")
    Listener listener() {
        return new listener();
    }
}

and also doesn't work.

Anybody have any idea how I can fix it? I guess I need to initialize injection of ApplicationContext into ListenerInitializer as late as possible due to need to initialize itself RabbitListenerEndpointRegistry, but how to do it?

Many thanks for any advice

edit: I call it to start through controller

@RequiredArgsConstructor
@RestController
class RestController {

       private final ListenerInitializer listenerInitializer;

    @GetMapping("/startListener")
    ResponseEntity<String> startListener() {
        listenerInitializer.startListener();
        return ResponseEntity.ok("Listener started.");
    }
}

CodePudding user response:

I don't know if this is going to help you somehow, but here is a fully working Spring Boot application:

@SpringBootApplication
public class So75236736Application {

    public static void main(String[] args) {
        SpringApplication.run(So75236736Application.class, args);
    }

    @Bean
    Listener listener() {
        return new Listener();
    }

    public static class Listener {

        @RabbitListener(queuesToDeclare = @Queue("myQueue"), id = "listener_id", autoStartup = "false")
        void handle(Object body) {
            System.out.println("Received: "   body);
        }

    }

    @Component
    public static class ListenerInitializer implements ApplicationContextAware {

        private ApplicationContext applicationContext;

        public void startListener() {
            RabbitListenerEndpointRegistry listenerRegistry =
                    this.applicationContext.getBean(RabbitListenerEndpointRegistry.class);
            listenerRegistry.getListenerContainer("listener_id").start();
            System.out.println("Listener started");
        }

        @Override
        public void setApplicationContext(ApplicationContext applicationContext) {
            this.applicationContext = applicationContext;
        }

    }

    @RestController
    public static class StartListenerController {

        private final ListenerInitializer listenerInitializer;

        public StartListenerController(ListenerInitializer listenerInitializer) {
            this.listenerInitializer = listenerInitializer;
        }

        @GetMapping("/startListener")
        ResponseEntity<String> startListener() {
            this.listenerInitializer.startListener();
            return ResponseEntity.ok("Listener started.");
        }
    }

}

Only difference that I don't use an @EnableRabbit explicitly, but rather rely on the auto-configuration. I also don't declare ListenerInitializer as a @Bean since it is already marked with @Component and that is enough for Spring Boot to scan it.

CodePudding user response:

Ok, I found the solution and sorry for bother you guys. Lack of knowledge. Still I don't know how it possible it works before, because I didn't changed anything, cause I was sure it should be like that, but solution was to move annotation @RabbitListener(queues = "myQueue2", id = "listener_id", autoStartup = "false") from over a class to over a method or add @RabbitHandler over a method.

Thank you @Artem Bilan for your help!

  • Related