spring-bootspring-aopnats.iobeancreationexception

How to avoid spring application failure due to BeanCreationException caused by third party package


I am using a third-party package in my spring boot app. This one to be specific. This package has a method that creates a bean when the application starts. The bean is only created successfully if this package is able to talk to nats service. In most cases, this all works fine. The remote server is available, the bean is created, my spring boot apps boots up correctly.

But there are some edge cases when remote nats servers might not be up. This causes my spring boot app to fail to start as the above function throws BeanCreationException

How can I avoid this i.e avoid my spring app boot failure due to this exception when the nats server is not up?

Note: It is fine for my spring app/business logic to be up and running if this bean (connections to nats service) is not available.

Specific Exception :

org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'natsConnection' defined in class path resource [io/nats/spring/boot/autoconfigure/NatsAutoConfiguration.class]:
Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.nats.client.Connection]:
Factory method 'natsConnection' threw exception; nested exception is java.io.IOException: Unable to connect to NATS server.\n\tat org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:655)\n\tat org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:635)\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1336)\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1176)\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:556)\n\tat org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:516)\n\tat org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:324)\n\tat org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)\n\tat org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:322)\n\tat org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)\n\tat org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:897)\n\tat org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:879)\n\tat 

Solution

  • The bean natsConnection is created by auto-configuration and annotated with @ConditionalOnMissingBean. Such beans are instantiated after your own beans.

    You can create your own bean of this type, io.nats.client.Connection, and register it as natsConnection. This bean should have no own logic. When called for the first time, it should create a worker instance via NatsAutoConfiguration.natsConnection(...) and then delegate all calls to it.

    Because of @ConditionalOnMissingBean the default bean from the NATS library will not be instantiated and only your bean will be created.