Harun Sevinc
Harun Sevinc

Reputation: 33

Spring-Boot AMQP create queues based on database data

I want to use my Spring-Boot application to create queues in RabbitMQ, based on some data in my Database. As example: I have an entity with some queue names. I need to create a new queue for each of them. Later on I want to use them without creating them.

I have allready created some configurations to create queues and bind them to an exchange. But my data in my database will change and for each new entry in a specific entity I will lateron need a new Queue.

One idea was to @Autowired in one of my @Configuraion a service, that gets the needed data from the Database. Unfortunately this did not work because the service I autowired got a BeanCreationException.

What am I doing wrong or is there another way to create queues based on database entries?

This is the class i build:

@Configuration
public class RabbitMQQueueConfiguration {

private QueueNameService queueNameService;

@Autowired
public RabbitMQQueueConfiguration(QueueNameService queueNameService){
    this.queueNameService =queueNameService;
}

private String queueA = getQueueNameA(1L);
private String queueB="queueB";


@Bean
public Queue queueA() {
    return new Queue(queueA);
}

@Bean
public Queue queueB() {
    return new Queue(queueB);
}

private String getQueueNameA(Long queueID){
    return queueNameService.getQueueName(queueID);
}
}

And here is the stacktrace i got:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rabbitMQQueueConfiguration' defined in file [...\classes\com\example\DemoRabbitMq\config\RabbitMQQueueConfiguration.class]: Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.DemoRabbitMq.config.RabbitMQQueueConfiguration$$EnhancerBySpringCGLIB$$bc4b2845]: Constructor threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "com.example.DemoRabbitMq.service.QueueNameService.getQueueName(java.lang.Long)" because "this.queueNameService" is null
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:313) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:294) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1356) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1203) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:551) ~[spring-context-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:758) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1237) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1226) ~[spring-boot-2.3.3.RELEASE.jar:2.3.3.RELEASE]
at com.example.DemoRabbitMq.DemoRabbitMqApplication.main(DemoRabbitMqApplication.java:24) ~[classes/:na]
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.example.DemoRabbitMq.config.RabbitMQQueueConfiguration$$EnhancerBySpringCGLIB$$bc4b2845]: Constructor threw exception; nested exception is java.lang.NullPointerException: Cannot invoke "com.example.DemoRabbitMq.service.QueueNameService.getQueueName(java.lang.Long)" because "this.queueNameService" is null
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:217) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:309) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
... 19 common frames omitted
Caused by: java.lang.NullPointerException: Cannot invoke "com.example.DemoRabbitMq.service.QueueNameService.getQueueName(java.lang.Long)" because "this.queueNameService" is null
at com.example.DemoRabbitMq.config.RabbitMQQueueConfiguration.getQueueNameA(RabbitMQQueueConfiguration.java:34) ~[classes/:na]
at com.example.DemoRabbitMq.config.RabbitMQQueueConfiguration.<init>(RabbitMQQueueConfiguration.java:19) ~[classes/:na]
at com.example.DemoRabbitMq.config.RabbitMQQueueConfiguration$$EnhancerBySpringCGLIB$$bc4b2845.<init>(<generated>) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) ~[na:na]
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481) ~[na:na]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:204) ~[spring-beans-5.2.8.RELEASE.jar:5.2.8.RELEASE]
... 21 common frames omitted

Edit: As requestet my service

@Service
public class QueueNameService {

private static final Logger LOGGER = LoggerFactory.getLogger(QueueNameService.class);

private final SomeOtherRepository someOtherRepository;
private final SomeRepository someRepository;


@Autowired
public QueueNameService(SomeOtherRepository someOtherRepository, SomeRepository someRepository) {
    this.someOtherRepository= someOtherRepository;
    this.someRepository= someRepository;
}

public String getQueueName(int tld_id) throws NoSuchElementException {
    Optional<Foo> foo= someOtherRepository.findById(foo_id);
    Optional<Bar> bar= someRepository.findById(foo.get().getBarId());
    return bar.map(Bar::getName).orElse(null);
}

}

Upvotes: 1

Views: 1004

Answers (1)

Artem Bilan
Artem Bilan

Reputation: 121177

You have a code like this:

private String queueA = getQueueNameA(1L);

which is called before constructor invocation. Since you try to get access to the property (queueNameService) which is initialized from the constructor therefore it ends up with that NullPointerException.

There is nothing Spring (or AMQP) specific in your problem: it is just general Java usage issue.

Upvotes: 1

Related Questions