Order of Autowiring in SpringBoot - spring

I would like Spring to inject Beans in a given order. I faced a strange issue with the code below. Both setAuthenticationProvider() and configureAuthManager() methods are injected in a random order. If configureAuthManager() is injected first, then during the login I get a NPE. Otherwise it works well.
So I want to force Spring to keep the order. I tried to annotate setAuthenticationProvider with Order(1) and the latter with Order(2) - did not help (why?). Then I also tried to to use #DependsOn annotation but it also didn't solve my problem.
#Configuration
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
private AuthenticationProvider authenticationProvider;
// #Order(1) - does not help
#Autowired
#Qualifier("daoAuthenticationProvider")
public void setAuthenticationProvider(AuthenticationProvider authenticationProvider) {
System.out.println("1");
this.authenticationProvider = authenticationProvider;
}
// #Order(2) - does not help
// #DependsOn("daoAuthenticationProvider") - does not help either
#Autowired
public void configureAuthManager(AuthenticationManagerBuilder authenticationManagerBuilder) {
System.out.println("2");
authenticationManagerBuilder.authenticationProvider(authenticationProvider);
}
[...]
}

The ordering of the bean creation shouldn't matter. If you need dependencies to be injected before you can call a method either
Use constructor based dependency injecetion
Add the argument to the method that needs it and use #Autowired (or #Bean if it creates a bean).
Either way Spring will be able to figure out in which order to create the beans to satisfy all the dependencies at the right time.

Related

If a class is already #Service, then does it need to be #Autowired in Spring Application class?

I'm following a tutorial and they #Service a class which in my mind should make it available to the whole application.
Why are the #Autowire-ing the class in Application?
Application:
#Configuration
#EnableAutoConfiguration // todo why not #SpringBootApplication
#ComponentScan
public class QuoteAppWsApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(QuoteAppWsApplication.class, args);
}
#Autowired
private EventBus eventBus; //
#Autowired // todo This is #Service...why is it be Autowired
private NotificationConsumer notificationConsumer;
NotificationConsumer:
#Service
public class NotificationConsumer implements Consumer<Event<NotificationData>> {
#Autowired
private NotificationService notificationService;
#Override
public void accept(Event<NotificationData> notificationDataEvent) { // .getData() belongs to Event<>
NotificationData notificationData = notificationDataEvent.getData(); //TODO Gets data from Event
try {
notificationService.initiateNotification(notificationData);
} catch (InterruptedException e) {
// ignore
}
}
}
#Service is a specialization of #Component. It is an annotation that tells Spring to include this class as a Bean in the Spring context. You can think of this as telling Spring what to pick up and put into the context during component scanning.
#Autowired is Spring's annotation to inject something from the context. You can think of this as you declaring what you want to get out of Spring. In general, you need to use this annotation on any field, constructor, or setter that you want Spring to invoke to supply you with the object that it's managing for the given type.
To answer your question, yes, you need both to declare what you want put into the context and when you want something out of the context.
Also, your first three annotations can be replaced with #SpringBootApplication. This annotation is a meta-annotation, meaning it's an annotation that it shorthand for including a series of other annotations. It's documented to include, among other things, all three of your annotations.

#RefreshScope side effects - auto-configuration, auto-wiring

I am using #RefreshScope annotation to refresh my beans after a change in Spring Config Server. This works fine but it has side effects in some cases.
First case: I have a bean CustomPermissionEvaluator that implements PermissionEvaluator (spring-security) in order to override default implementation (DenyAllPermissionEvaluator).
import org.springframework.security.access.PermissionEvaluator;
#Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
#Override
public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
If I annotate CustomPermissionEvaluator with #RefreshScope, Spring no longer take it into account and the default implementation is chosen over this custom implementation.
Second case: I have the following bean:
#Bean
#Profile("enable_mongo_ssl")
public MongoClientOptions mongoClientOptions() {
return getMongoClientOptionsBuilder()
.build();
}
If I annotate it with #RefreshScope, MongoAutoConfiguration is not taking it when building MongoClient and default mongoClientOptions with no certificate is instead used.
Last case:
I have an object mapper defined:
#Bean
#Primary
public ObjectMapper defaultObjectMapper() {
return ObjectMapperProvider.defaultObjectMapper();
}
If I annotate it with #RefreshScope, I get the following error:
more than one 'primary' bean found among candidates: [defaultObjectMapper, jacksonObjectMapper]
I guess those examples have to do with the fact the #RefreshScope annotation causes the bean to be proxied.
But is there a clean way to keep using this annotation and make those features work?

Spring #Component & #Bean annotation

I believe #Configuration annotation when used in conjunction with #Bean annotation in spring is used to replace xml configuration. However I saw a piece of code where #Bean was used in conjunction with #Component (defined at class level). Is this a valid declaration? Are there any any pros / cons in using #Component with #Bean annotation vs using #Configuration and #Bean.
EDIT:
Thanks #Sundar & #Biju. I did programmatic call between 2 bean methods under Component class. I saw different object values. However when I used Configuration , I saw the same bean values. Based on what you had explained , I assume a regular method call was made when I used #Component , whereas when I used #Configuration , I assume method annotated with #Bean was treated as a Spring Bean
Code
#Component
public class AppConfig {
#Bean(name="customerService")
public CustomerService getCustomerService(){
System.out.println(getService());
System.out.println(getService());
return getService();
}
#Bean
public CustomerService getService(){
return new CustomerServiceImpl();
}
}
Console Output
com.company.service.CustomerServiceImpl#68bbe345
com.company.service.CustomerServiceImpl#30b8a058
Code
#Configuration
public class AppConfig {
#Bean(name="customerService")
public CustomerService getCustomerService(){
System.out.println(getService());
System.out.println(getService());
return getService();
}
#Bean
public CustomerService getService(){
return new CustomerServiceImpl();
}
}
Console Output
com.company.service.CustomerServiceImpl#71623278
com.company.service.CustomerServiceImpl#71623278
It is a valid declaration, however there are catches - the one within a #Component is referred to as a lite-mode and dependencies cannot easily be injected for beans declared in this form. The recommendation is always to use #Bean in a #Configuration annotated class - here is a good reference on this - http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-java-basic-concepts
You can use #Component as an alternative for #Configuration. It’s official suggestion from spring team.
Simply declare your #Bean methods on classes not annotated with #Configuration (but typically with another Spring stereotype instead, e.g. #Component). As long as you don’t do programmatic calls between your #Bean methods, this is going to work just as fine, but conditions apply*.
Please refer more info in this link.
http://dimafeng.com/2015/08/29/spring-configuration_vs_component/

Spring JavaConfig + WebMvcConfigurerAdapter + #Autowired => NPE

I have an application with 2 Contexts. Parent for web agnostic business logic and ChildContext (implicitly created by dispatcher servlet) for web logic.
My setup loks like
#Configuration
public class BusinessConfig {
#Bean
public ObjectMapper jacksonMapper() { return new ObjectMapper() }
}
and
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired
private ObjectMapper objectMapper; // <- is null for some reason
#Override
public configureMessageConverters(List<HttpMessageConverter<?>> converters) {
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(objectMapper); // <- bang!
messageConverters.add(converter);
}
}
I need the the object mapper in the parent context, as I use it also in security configuration. But can someone explain me, why the #Autowired objectMapper is null? Its created in the parent context (the fact that the parent exists is even logged by spring at startup). Also #Autowired has required=true by default, so it should not blow up in the configure method (it should have blown up in construction of the context, if the bean wasn't there for some reason).
It seems to me that there might be some lifecycle problem in spring - in a sense that it calls the overridden methods first, and then #Autowires the dependencies... I have also tried to #Autowire the BusinessConfig (should be perfectly legal according to documentation - the result was the same (null)).
What should I do to make this working?
Thanks in advance!
EDIT - ISSUE FOUND
I found the issue. Unfortunately it had nothing to do with WebMvcConfigurerAdapter nor #Configuration. It was caused by premature initialization of context triggered by missing static modifier for propertyPlaceholderConfigurer... I have created issue in Spring core jira (https://jira.spring.io/browse/SPR-14382)
What about simply renaming the bean declaration method to match with the autowired bean?
#Configuration
public class BusinessConfig {
#Bean
public ObjectMapper objectMapper() { return new ObjectMapper() }
}
#Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired
private ObjectMapper objectMapper;
[...]
}

Spring #Autowired value is not fully initialized

Given the following code:
public class MyService implements InitializingBean {
#Autowired
private Set<MyDep> allDeps;
#Override
public void afterPropertiesSet() {
... use 'allDeps' here ...
}
}
MyDep is an interface with three different implementations all of which also implement InitializingBean (by extending the same abstract base class).
When I go to use allDeps during set up of MyService only 2 out of the 3 injected instances are themselves fully initialized. One of the instances is constructed and injected, but it's afterPropertiesSet() has not yet been run. In the other two instances it has been run.
It's been my understanding that Spring will run afterPropertiesSet() on a bean only after all of its dependencies are injected, and they will only be injected once they're fully initialized. Perhaps my understanding is wrong? Is this a bug in Spring? I've also tried using getBeansOfType(MyDep.class) with the same results.
FWIW, looks like there's an similar unanswered question from 2 years ago. So perhaps it's time to re-ask?
Spring dependency injection not completing in time
Given that it turns out there is a cyclic dependency in my bean definitions, the solution is to wait until the full context is created before doing the initialization in MyService.
Perhaps not the best solution, given that anything that depends on MyService in its set-up could have problems, but I don't currently have any of those. So, this seems to do the trick for me:
public class MyService implements ApplicationListener<ContextRefreshedEvent> {
#Autowired
private Set<MyDep> allDeps;
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
... now I can use 'allDeps' here ...
}
}

Resources