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!