CommandLineRunner VS SmartLifecycle - spring-boot

with #PostConstruct and autowiring a MessageChannel problem, I found a solution SmartLifecycle.start()
can one also use CommandLineRunner?
what is the best way to start work with MessageChannel rabbitMQ after a full initialization of the context?

Spring Boot's CommandLineRunner (or ApplicationRunner) is fine.
SmartLifecycle is available for any Spring application, not just Boot applications.

Related

How does AuthenticationManager implementation gets instantiated in SpringBoot App

Including spring security starter dependency makes AuthenticationManager available in a spring boot application. I can simply Autowire the AuthenticationManager. How does SpringBoot understand to automatically instantiate the bean for AuthenticationManager though it is in a very different jar file ?
for e.g.
I can simply write
#Autowire
AuthenticationManager authManager;
in my SpringBoot App after including the dependency. How does spring know that it is supposed to instantiate which class and how ?
The class org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration imports the configuration class org.springframework.boot.autoconfigure.security.AuthenticationManagerConfiguration, which then provides the bean for the AuthenticationManager (it will use a builder to build the authentication manager according to the configuration which is provided).

WebApplicationContext is always null in a spring boot test

My test class looks like this
#SpringBootTest(webEnvironment=WebEnvironment.MOCK)
public class sampleClassTest{
#Autowired
private WebApplicationContext wac;
}
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
In the setup method, wac is always null. From spring boot documentation, #SpringBootTest(webEnvironment=WebEnvironment.MOCK) always created a mock WebapplicaitonContext.
So I would expect it get autowired in the code above which doesn't happen.
Can someone tell me how to go about creating a webapplicationContext in this case so that it's not null like in my case ?
UPDATE
I am running spring boot tests invoking them from a class with springboot annotation.
Both test (springboottest) and calling class (springboot) application are in the same spring boot project under src/main/java.
I have nothing under src/main/test. I have done in this way because if classes from src/main/java want to call a test class then, it isn't really a test class.
Now, the problem is that I can't use runWith(SpringRunner.class) in springbootTest class. If I did that to get a mock webApplicationContext then, it gives me this error:
javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Admin,name=SpringApplication
I am not sure how to do about this.
To use #SpringBootTest you need to use Spring Framework's test runner. Annotate your test class with #RunWith(SpringRunner.class).
If someone is struggling with this issue in 2022 - please keep my defined precondions in mind. If you are using #SpringBootTest with defined port and constructor auto-wiring of the test class, the application context might be null.
It seems that the constructor dependency injection is eager and the cache aware context delegate of Spring is searching for a web application context which is no available yet. If you use field auto-wiring your test might run in a deterministic manner.
Whoever is facing this issue, make sure your spring boot starter parent version is compatible with spring cloud version in pom.xml
I was facing same issue, i resolved it by doing same.

Disabling Spring JMS Auto configuration in Spring Boot Application

In my spring boot application i configure two different instances of MQQueueConnectionFactory (different id) as it is a need of the application. For that i have added ibm client jars.
I have also added spring-jms dependency in my code as i wanted JmsTemplate etc classes. After adding this dependency, JmsAutoConfiguration finds JmsTemplate in classpath and tries to configure beans. In this process, it tries to inject bean of type ConnectionFactory and this is where the code fails and i start getting the error. Below is the code from JmsAutoConfiguration
#Configuration
#ConditionalOnClass(JmsTemplate.class)
#ConditionalOnBean(ConnectionFactory.class)
#EnableConfigurationProperties(JmsProperties.class)
#Import(JmsAnnotationDrivenConfiguration.class)
public class JmsAutoConfiguration {
#Autowired
private JmsProperties properties;
#Autowired
private ConnectionFactory connectionFactory;
#Autowired(required = false)
private DestinationResolver destinationResolver;
Do i have a facility to switch off JmsAutoconfiguration feature of spring boot by any chance? If not then what is the alternative solution for this?
You can add the auto configurations, which you want to disable, to the SpringBootApplication annotation:
#SpringBootApplication(exclude = JmsAutoConfiguration.class)
FYI, use this to disable ActiveMQ
#SpringBootApplication(exclude = ActiveMQAutoConfiguration.class)
if want to control it via the properties (in this case a application.yml) then you can do something like this.
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration
In my case it worked after excluding both classes :
#EnableAutoConfiguration(exclude={JmsAutoConfiguration.class, ActiveMQAutoConfiguration.class})

How can I start a service in Spring Boot when the server has started?

I have a service (bean) that cannot be activated before the jetty server has started.
Is there a way to achieve that easily with Spring/Spring Boot?
Regards,
Jakob
If you use JavaConfig (which i assume you do with Spring Boot) you can use the DependsOn annotation with the bean name of the HealthEndpoint (with the default auto configuration, the bean name of the health endpoint is healthEndpoint):
#Bean
#DependsOn("healthEndpoint")
public YourService yourService() {}
You could have your service bean implement SmartLifecycle and set it to auto-start. It will be started only once the application context has been refreshed.

Multiple DataSource beans with Spring Boot Actuator's EndpointAutoConfiguration possible?

I have a spring-boot application that uses several DataSource beans and would still like to use the EndpointAutoConfiguration from spring-boot-actuator that is loaded as part of using the #EnableAutoConfiguration annotation. This doesn't seem possible as there is a DataSource bean injected into EndpointAutoConfiguration to setup the HealthEndpoint bean. Due to the multiple instances of DataSource that exist in my application, a NoUniqueBeanDefinitionException is thrown upon application startup unless I exclude EndpointAutoConfiguration but then I must setup all the other endpoints manually (/env, /metrics, etc).
Is there a better way to do this?
You could mark one of your DataSources as #Primary or you could provide your own HealthIndicator (it's not the endpoint that wants your DataSource but that bean, which is designed to be overridden by just adding one of your own).

Resources