I am using Spring Framework 4.
I have a class (say ClassA) in which another class (say ClassB) is been used. ClassA's member variables are getting value from ClassB. ClassB has a static method which read data from properties file. In ClassB a static member variable ApplicationContext is been injected using #Autowired annotation.
What I want is, I want to make sure that when ClassA uses's its member variable it should get all set with values read from properties file. And for that ClassB should get ApplicationContext all set to read from MessageSource.
As ClassA is marked as #Component, Spring loads ClassA, but when it tries to initialize member variables, it is getting NullPointerException, as ApplicationContext is not yet initialized.
So my question here is, Is there any way available to let Spring tell that some bean should be initialized at some order or something like that. I tried using #DependsOn annotation and specified #Bean to the getter method of ApplicationContext. But it gives below exception:
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'applicationContext': Requested bean is currently in creation: Is there an unresolvable circular reference?
Any idea on this issue?
Thanks
Thanks for comments.
I found the solution in one of the annotations supplied by Spring Framework.
Solution of #DependsOn annotation worked. Actually when I was using #Bean above getter method of ApplicationContext it was firing exception as mentioned in the question. Then I read the documentation of #DependsOn annotation. It states that this annotation is applicable on #Bean and #Component. As the class in which ApplicationContext was being injected, I've made ClassA #DependsOn the #Component class where ApplicationContext is being injected and it works.
Thanks again for your comments.
If your purpose is to use a MessageSource, use the built-in support, as explained here.
In general, don't #Autowire static fields, use #Value and PropertySourcePlaceholderConfigurer for properties.
Here a good example for the solution given by #Parth Bhagat.
https://www.baeldung.com/spring-depends-on
Related
Let's look at the following example
#Service
class AServiceImpl{
#Autowired
BService bservice
}
#Service
class BServiceImpl{
#Autowired
AService aservice
}
I know the Spring uses three-level cache to solve Circular Dependency issues. When A is being initialized and B is being injected, Spring begins to initialize B, which needs bean of A to be injected. But A is not fully initialized yet, so B just get a reference to a non-fully initialized bean of A from cache.
But in Spring, if AService is with a #Transactional annotation, Spring will construct an proxy Bean for A using BeanPostProcessor, and this process happens after #Autowired. This means, although B have a a reference to a non-fully initialized bean of A from cache, the reference is not pointing to the proxy bean, which doesn't seem to be correct. Is there anything wrong with my reasoning?
There is a saying the #Lazy could solve spring Circular Dependencies problem. According to my understanding, there are two types of usage of this annotation.
#Lazy
#Service
class AServiceImpl{
#Autowired
BService bservice
}
or
#Service
class BServiceImpl{
#Lazy
#Autowired
AService aservice
}
Some explanation of this annotation says that the annotated bean will be initialized if it is referenced by another bean. But I think whether with it or without it, "the annotated bean will always be initialized if it is referenced by another bean", so how can it solve the circular dependency problem?
Some other explanation says that the annotated bean will be initialized if its methods are invoked, this sound reasonable, but I tried and it seems to me that even if none of methods in AService is called, B can still hold the reference to the final proxy bean of AService, what is wrong with my try?
Another way is inside a constructor
#Autowired
public AService(#Lazy BService bservice) {
this.bservice = bservice;
}
instead of fully initializing the bean, it will create a proxy to inject it into the other bean. The injected bean will only be fully created when it’s first needed.
I have a Configuration class that is implementing BeanDefinitionRegistryPostProcessor , In this I have to take some properties from the Property file use them in the postProcessBeanDefinitonRegistry. When I try to autowire the ApplicationContext I noticed that the ApplicationContext object is coming as null and so does all the other injected objects. On looking into the explanation for "BeanDefinitionRegistryPostProcessor" I came to know that it executes early.
Question is :: How do I read my property values in the class that is implementing BeanDefinitionRegistryPostProcessor?
I have resolved the above issue. I understood that for my code logic "BeanDefinitionRegistryPostProcessor" is not suitable. For my scenario I had to implement the "ApplicationContextAware" interface.
I have a bean declared in by config file as:
#Bean
#Lazy
#Scope("prototype")
public SomeClass someClass()
{
return new SomeClass();
}
Then inside my test class I have the following code:
#Autowired
private SomeClass someClass;
#Before
public void setUp()
{
xyzObject.someMethod(someClass);
}
My question here is inside my setUp() method I am just referencing the autowired SomeClass bean but not getting it from the spring context using getBean(), but still it is creating a new bean everytime the setUp() is running before a test. Why is this happening? Does prototype scope means a new bean gets created whenever the bean's reference is used anywhere in the code? I haven't seen anything specified like that in the documentation.
That is the essence of Inversion of Control. Because you injected it into another bean, every time you instantiate another bean your injected bean would be created and provided by spring as part of instantiation of your containing bean. You don't need to call getBean() here. However if in some place you just need an instance of your SomeClass bean you may call getBean() to tell your spring environment to give you that bean to you. However, It is better to avoid such practice and rely on injection. Or create a Factory that can provide you such Bean (Still relaying on spring though) That would make your code not aware of Spring which is IMHO is more ellegant
I have a situation and im trying to figure out why it is so. The scenario is I have a class A that implements an operation exposed by a webservice. For each request for the operation a new instance of A is created. The entire thing is manged by Spring internally and I am not sure how exactly the Class A in instantiated by the webservice.
Now i have a class variable whose value i want to inject during runtime through
#Value("${someValue}")
String someVariable
someValue is defined a system property. But each of the beans created has someVariable as NULL.
I tried the same thing in another class annotated with #Configuration in the same package and it is resolving the variable fine.
So, Im thinking if the ability to inject through #Value depends on the way a bean is created like #Component, #Configuration-#Bean, XML definiti
Not really. Actually You can inject value with #Value in both the component scan bean and xml definition bean. But pay attention to this, It depends on which xml file that you put the Placeholder in, it just valids in the per-container. For example, you put it in applicationContext, then the bean create in xxx-servlet.xml can not inject value with #Value.
I have a circular reference in one of my projects at work using spring, which I am unable to fix, and fails with the following error at startup:
'org.springframework.security.authenticationManager': Requested bean is currently in creation: Is there an unresolvable circular reference?
I tried to recreate the same problem at a smaller level in a sample project (without all the details of my work project). I have however been unable to come up with a plausible scenario where spring fails with an error.
Here's what I have:
public class ClassA {
#Autowired
ClassB classB;
}
public class ClassB {
#Autowired
ClassC classC;
}
#Component
public class ClassC {
#Autowired
ClassA classA;
}
#Configuration
public class Config {
#Bean
public ClassA classA() {
return new ClassA();
}
#Bean
public ClassB classB() {
return new ClassB();
}
}
I have a similar scenario in my project, which fails, and I was expecting spring to complain in my sample project as well. But it works fine! Can someone give me a simple example of how to break spring with the circular reference error?
Edit: I fixed the issue using javax.inject.Provider. The only other difference in the 2 projects was the annotations used were javax.inject.Inject and javax.annotation.ManagedBean in place of #Autowired and #Component.
You could use #Lazy to indicate that the bean is lazily created, breaking the eager cycle of autowiring.
The idea is that some bean on the cycle could be instantiated as a proxy, and just at the moment it is really needed it will be initialized. This means, all beans are initialized except the one that is a proxy. Using it for the first time will trigger the configuration and as the other beans are already configured it will not be a problem.
From one Issue in Spring-Jira:
#Lazy annotation that can be used in conjunction with #Configuration
to indicate that all beans within that configuration class should be
lazily initialized. Of course, #Lazy may also be used in conjunction
with individual #Bean methods to indicate lazy initialization on a
one-by-one basis.
https://jira.springsource.org/browse/SJC-263
Meaning that annotating your bean as #Lazy would be enough. Or if you prefer just annotate the configuration class as #Lazy as follows:
#Configuration
#Lazy
public class Config {
#Bean
public ClassA classA() {
return new ClassA();
}
#Bean
public ClassB classB() {
return new ClassB();
}
}
If you implement an interface of your beans this will work quite well.
This is an old thread, so I guess you almost forgot about the issue, but I want to let you know about the mystery. I encountered the same problem, and mine didn't go away magically, so I had to resolve the problem. I'll solve your questions step by step.
1. Why you couldn't reproduce the circular reference exception?
Because Spring takes care of it. It creates beans and injects them as required.
2. Then why does your project produce the exception?
As #sperumal said, Spring may produce circular exception if you use constructor injection
According to the log, you use Spring Security in your project
In the Spring Security config, they do use constructor injection
Your beans which injects the authenticationManager had the circular reference
3. Then why has the exception gone away mystically?
The exception may or may not occur depends on the creation order of beans. I guess you made several *context.xml files or so, and load them with config something like below in web.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:*-context.xml</param-value>
</context-param>
The xml files will be loaded by XmlWebApplicationContext class and the loading order of files are not guaranteed. It just loads files from the file system. The problem is here. There's no problem if the class loads the application context file first, because your beans are already created when they are used for the construction injection of Spring Security. But, if it loads the Spring Security context file first, the circular reference problem occurs, because Spring tries to use your beans in the constructor injection before they had been created.
4. How to solve the problem?
Force the loading order of the xml files. In my case, I loaded the security context xml file at the end of the application context file by using <import resource="">. The loading order can be changed depends on environments even with the same code, so I recommend setting the order to remove potential problems.
According to Spring documentation, it is possible to get Circular dependency issue or BeanCurrentlyInCreationException by using constructor injection.
The solution to fix the issue is to use setters instead of Constructor injection.
Reference http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html.