Spring #Autowired value is not fully initialized - spring

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 ...
}
}

Related

Dependency injection through constructor vs property [duplicate]

So since I've been using Spring, if I were to write a service that had dependencies I would do the following:
#Component
public class SomeService {
#Autowired private SomeOtherService someOtherService;
}
I have now run across code that uses another convention to achieve the same goal
#Component
public class SomeService {
private final SomeOtherService someOtherService;
#Autowired
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
Both of these methods will work, I understand that. But is there some advantage to using option B? To me, it creates more code in the class and unit test. (Having to write constructor and not being able to use #InjectMocks)
Is there something I'm missing? Is there anything else the autowired constructor does besides add code to the unit tests? Is this a more preferred way to do dependency injection?
Yes, option B (which is called constructor injection) is actually recommended over field injection, and has several advantages:
the dependencies are clearly identified. There is no way to forget one when testing, or instantiating the object in any other circumstance (like creating the bean instance explicitly in a config class)
the dependencies can be final, which helps with robustness and thread-safety
you don't need reflection to set the dependencies. InjectMocks is still usable, but not necessary. You can just create mocks by yourself and inject them by simply calling the constructor
See this blog post for a more detailed article, by one of the Spring contributors, Olivier Gierke.
I will explain you in simple words:
In Option(A), you are allowing anyone (in different class outside/inside the Spring container) to create an instance using default constructor (like new SomeService()), which is NOT good as you need SomeOtherService object (as a dependency) for your SomeService.
Is there anything else the autowired constructor does besides add code
to the unit tests? Is this a more preferred way to do dependency
injection?
Option(B) is preferred approach as it does NOT allow to create SomeService object without actually resolving the SomeOtherService dependency.
Please note, that since Spring 4.3 you don't even need an #Autowired on your constructor, so you can write your code in Java style rather than tying to Spring's annotations.
Your snippet would look like that:
#Component
public class SomeService {
private final SomeOtherService someOtherService;
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
Good to know
If there is only one constructor call, there is no need to include an #Autowired annotation. Then you can use something like this:
#RestController
public class NiceController {
private final DataRepository repository;
public NiceController(ChapterRepository repository) {
this.repository = repository;
}
}
... example of Spring Data Repository injection.
Actually, In my experience, The second option is better. Without the need for #Autowired. In fact, it is wiser to create code that is not too tightly coupled with the framework (as good as Spring is). You want code that tries as much as possible to adopt a deferred decision-making approach. That is as much pojo as possible, so much such that the framework can be swapped out easily.
So I would advise you create a separate Config file and define your bean there, like this:
In SomeService.java file:
public class SomeService {
private final SomeOtherService someOtherService;
public SomeService(SomeOtherService someOtherService){
this.someOtherService = someOtherService;
}
}
In ServiceConfig.java file:
#Config
public class ServiceConfig {
#Bean
public SomeService someService(SomeOtherService someOtherService){
return new SomeService(someOtherService);
}
}
In fact, if you want to get deeply technical about it, there are thread safety questions (among other things) that arise with the use of Field Injection (#Autowired), depending on the size of the project obviously. Check this out to learn more on the advantages and disadvantages of Autowiring. Actually, the pivotal guys actually recommend that you use Constructor injection instead of Field Injection
I hope I won't be downgraded for expressing my opinion, but for me option A better reflects the power of Spring dependency injection, while in the option B you are coupling your class with your dependency, in fact you cannot instantiate an object without passing its dependencies from the constructor. Dependency Injection have been invented for avoid that by implementing Inversion of Control,so for me option B doesn't have any sense.
Autowired constructors provides a hook to add custom code before registering it in the spring container. Suppose SomeService class extends another class named SuperSomeService and it has some constructor which takes a name as its argument. In this case, Autowired constructor works fine. Also, if you have some other members to be initialized, you can do it in the constructor before returning the instance to spring container.
public class SuperSomeService {
private String name;
public SuperSomeService(String name) {
this.name = name;
}
}
#Component
public class SomeService extends SuperSomeService {
private final SomeOtherService someOtherService;
private Map<String, String> props = null;
#Autowired
public SomeService(SomeOtherService someOtherService){
SuperSomeService("SomeService")
this.someOtherService = someOtherService;
props = loadMap();
}
}
I prefer construction injection, just because I can mark my dependency as final which is not possible while injecting properties using property injection.
your dependencies should be final i.e not modified by program.
There are few cases when #Autowired is preferable.
One of them is circular dependency. Imagine the following scenario:
#Service
public class EmployeeService {
private final DepartmentService departmentService;
public EmployeeService(DepartmentService departmentService) {
this.departmentService = departmentService;
}
}
and
#Service
public class DepartmentService {
private final EmployeeService employeeService;
public DepartmentService(EmployeeService employeeService) {
this.employeeService = employeeService;
}
}
Then Spring Bean Factory will throw circular dependency exception. This won't happen if you use #Autowired annotation in both beans. And this is understandable: the constructor injection happens at very early stage of Spring Bean initialization, in createBeanInstance method of Bean Factory, while #Autowired-based injection happens way later, on post processing stage and is done by AutowiredAnnotationBeanPostProcessor.
Circular dependency is quite common in complex Spring Context application, and it needs not to be just two beans referring one another, it could a complex chain of several beans.
Another use case, where #Autowired is very helpful, is self-injection.
#Service
public class EmployeeService {
#Autowired
private EmployeeService self;
}
This might be needed to invoke an advised method from within the same bean. Self-injection is also discussed here and here.
There is a way to inject the dependencies through constructor using #RequeiredArgsContructor annotation from Lombok
#RequiredArgsConstructor
#Service
class A {
private final B b // needs to be declared final to be injected
}
In this way you don't need to specify a constructor

Order of Autowiring in SpringBoot

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.

Spring #Autowired behavior different in tests than components

Are the rules/behaviors around #Autowired different when writing tests? It seems that with a test, you can autowire to a concrete type, but if you try the same thing inside a #Component it will fail. This is a contrived example, but it's something I ran into and am just trying to understand better.
Contrived example code:
public interface Gizmo {
void whirr();
}
#Configuration
public class GizmoConfiguration {
#Bean
#Profile("no-dependencies")
public Gizmo fooGizmoBean() {
return new FooGizmo();
}
#Bean
#Profile("!no-dependencies")
public Gizmo barGizmoBean() {
return new BarGizmo();
}
public class FooGizmo implements Gizmo {
#Override
public void whirr() {
}
}
public class BarGizmo implements Gizmo {
#Override
public void whirr() {
}
}
}
Test that runs fine:
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles(Application.Profiles.NO_DEPENDENCIES)
public class TestClass {
#Autowired
private GizmoConfiguration.FooGizmo gizmo;
#Test
public void test() {
assertNotNull(gizmo);
}
}
Component that causes java.lang.IllegalStateException: Failed to load ApplicationContext:
#Component
public class TestComponent {
#Autowired
private GizmoConfiguration.FooGizmo gizmo;
}
because of:
No qualifying bean of type 'GizmoConfiguration$FooGizmo' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Are the rules/behaviors around #Autowired different when writing
tests?
Not exactly: the rules are actually exactly the same. The difference is in terms of timing with regard to how Spring determines if a given bean is an autowire candidate.
It seems that with a test, you can autowire to a concrete type,
but if you try the same thing inside a #Component it will fail.
I understand why you would think that, since your example demonstrates that behavior, but your analysis is not exactly correct.
So let me explain...
When Spring attempts to perform autowiring for your #Component class, the only information it has about types (i.e., classes and interfaces) for beans coming from #Bean methods is the information available in an #Bean method's formal signature.
In your example, when Spring searches for so-called "autowire candidates" to inject into your #Component, Spring only sees a bean of type Gizmo for your fooGizmoBean() #Bean method. So that's why you see the "No qualifying bean of type 'GizmoConfiguration$FooGizmo'" error, which happens to be completely correct.
If you want Spring to be able to autowire your #Component using the concrete type, you will have to redefine the signature of your fooGizmoBean() #Bean method to return FooGizmo instead of Gizmo.
So, that's the first half of the story. The second half of the story is why the Spring TestContext Framework is able to perform autowiring by the concrete type for the test instance.
The reason that works is that the ApplicationContext has already been completely started (i.e., all beans have been instantiated and all #Bean methods have been invoked by the container) by the time the testing framework attempts to perform dependency injection. By that point in time, the fooGizmoBean() method has already been invoked by Spring, and Spring now knows the concrete type is actually a FooGizmo. Thus, #Autowired FooGizmo gizmo; works in the test.

if there are more than one classes implementing one interface ,then how does #autowired work? [duplicate]

This question already has an answer here:
Autowired.. more than one?
(1 answer)
Closed 7 years ago.
(spring mvc)first i do not know whether the writing below are right or not.if it is right ,then i don't understand how the #autowired works here.if it is wrong , then how i should do when i have more than one classes to implement one interface.
public interface UserDao{
public User findUserByUserName(String username);
}
public class UserDaoImpl1 implements UserDao{
#Override
public User findUserByUserName(String username){
.......
}
}
public class UserDaoImpl2 implements UserDao{
#Override
public User findUserByUserName(String username){
.......
}
}
#Service
public class UserServiceImpl implements UserService{
#Autowired
private UserDao userDao;//how does atuowired work here?
#Override
public User loginCheck(User user){
......
}
}
When you have more than one class you can do two things:
Use #Qualifierannotation and tell which implementation should be injected (spring default qualifier is name of bean) so doing this will inject second bean implementation:
#Autowired
#Qualifier("userDaoImpl2")
private UserDao userDao;
You can use #Primary on beans so that one implementation would be always preferred over another when there are more than one and interface is #Autowire.
Choice can be made based on side which should know about autowiring, if you want classes which are injected with dependencies to be ease to change and unaware of implementation details you should go with option 2 and if you want to control dependencies option 1 is better choice.
If more than one option exists Spring should throw exception (so your code should throw exception telling you more than one candidate for autowiring exists). It should look like:
nested exception is
org.springframework.beans.factory.NoSuchBeanDefinitionException: No
unique bean of type
[com.package.name.UserDao] is defined:
expected single matching bean but found 2: [userDaoImpl1, userDaoImpl2]
Here is good link that explains details.

Trying to generate error about Spring's #Autowired field injection for JUnit

I am working with Spring 4.0.7, and with JUnit about testing of course.
About DI Spring offers #Autowired to be used in three locations
constructor
setter
field
I always work through the two first, why never the third option?
Because I remember have read long time ago about field injection should not be used, because it has a negative consequence about Testing. It does JUnit fails.
Note: Only for Testing is the problem. To runtime or production all goes well
Objective: For demonstration/academic purposes I want generate this problem.
I have the following:
Repository
public interface PersonRepository extends JpaRepository<Person, String>{
}
A Service
#Service
#Transactional
#Profile("failure")
public class PersonFailTestServiceImpl implements PersonService {
private static final Logger logger = ...
#Autowired
private PersonRepository personRepository;
Other Service (calling or using the service shown above)
#Service
#Transactional
#Profile("failure")
public class PersonFailTestProcessImpl implements PersonProcess {
private static final Logger logger = ...
#Autowired
private PersonService personService;
How you can see the two services are based on Field Injection.
Now the testing:
How the beans are loaded
#Configuration
#ComponentScan( basePackages={"com.manuel.jordan.server.infrastructure"},
basePackageClasses={PersonProcess.class,PersonRepository.class, PersonService.class})
public class CentralConfigurationEntryPoint {
}
#ContextConfiguration(classes=CentralConfigurationEntryPoint.class)
public class CentralTestConfigurationEntryPoint {
}
Now the two testing classes
#Transactional
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles({"development","failure"})
public class PersonServiceImplDevelopmentFailureTest extends CentralTestConfigurationEntryPoint {
#Autowired
private PersonService personService;
#Test
public void savePerson01(){
Person person01 = PersonFactory.createPerson01();
personService.save(person01);
personService.printPerson(personService.findOne("1"));
}
#Transactional
#RunWith(SpringJUnit4ClassRunner.class)
#ActiveProfiles({"development","failure"})
public class PersonProcessImplDevelopmentFailureTest extends CentralTestConfigurationEntryPoint{
#Autowired
private PersonProcess personProcess;
Well all the testing methods pass, all green. I don't know if I am missing something or through Spring 4 the problem has been fixed
If this was your premise or problem
Because I remember have read long time ago about field injection
should not be used, because it has a negative consequence about
Testing. It does JUnit fails.
then you thought wrong. There is nothing inherently wrong with using field injection, definitely nothing that would cause JUnit tests to fail in and of itself. If a bean exists, Spring will be able to inject it whether it's in a constructor, a setter method, or a field.
Since you've activated your failure profile, your PersonFailTestServiceImpl bean will be found.
I think I can help. The example code you've posted here is a good example of a system / integration test, not a UNIT test.
If you were UNIT testing PersonFailTestProcessImpl, you would have to set the personRepository dependency yourself through code. But it is private, so how do you do this? You cannot use a constructor or setter since none is provided. This is what is meant by 'hard to unit test'.
Java 5+ provides a way to set private variables like this via reflection (the so-called privileged accessor). Basically, you obtain the class, get the declared field, call its setAccessible method, then you can set its value directly. There are libraries that will do these steps for you, but the point is that this is a pain compared to X.setSomething();
So there is nothing that 'makes jUnit fails' by using #Autowired on a private field. But building an object model without constructors or setters for establishing dependencies is unnecessarily constraining.

Resources