Spring circular reference example - java

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.

Related

How to Lazy load all the Spring beans whether it is defined by #Bean or #Component in Springboot 2.2

I am writing a spring application which is interactive and basically handles lots of commands like create, list, update, delete various types of resources.
For now, just assume a single run of the application handles only a single command and the program exits.
For all the classes to validate command, execute the command, required factory classes for each resource there is a separate class and each class is annotated with #Component annotation for spring to manage all the components.
There are also some of the manually defined beans by #Bean method.
Now that my application first identifies what kind of command is executed (create, delete, list, update, etc), I want the only beans of that command to be created and Autowired wherever required (after taking command from user) and I want to avoid the creation of dozens of beans related to other commands.
On searching, I came to know about Lazy instantiation of Beans that spring provides.
However, I am not sure if it is the weapon I am searching for.
What I tried
Very first I found #Lazy annotation, but since I want to lazily load all the Beans, I don't want to write #Lazy everywhere in each class.
Then I found setting below property in application.yml does the work.
spring:
main:
lazy-initialization: true
I tried that but still, it is not lazily creating the beans.
My application.yml files looks like this
spring:
main:
lazy-initialization: true
My main SpringBootApplication file looks like this:
#Slf4j
#SpringBootApplication
public class SpringBootApplication {
public static void main(String[] args) {
System.out.println("Loading Application...");
ApplicationContext context = SpringApplication.run(SpringBootApplication.class, args);
final AtomicInteger counter = new AtomicInteger(0);
log.info("**************** START: Total Bean Objects: {} ******************", context.getBeanDefinitionCount());
Arrays.asList(context.getBeanDefinitionNames())
.forEach(beanName -> {
log.info("{}) Bean Name: {} ", counter.incrementAndGet(), beanName);
});
log.info("**************** END: Total Bean: {} ******************", context.getBeanDefinitionCount());
}
}
My other classes looks like this:
#Component
#RequiredArgsConstructor(onConstructor = #__(#Autowired))
public class MyClass1 implements ResourceCreator<MyClass2, MyClass3> {
private final RequestValidatorImpl requestValidator;
private final ResourceCreator resourceCreator;
#Override
public MyClass2 toImplementFunction(MyClass3 myclass3) {
//logic
}
On running the application, It prints all the classes where I annotated #Component as well as beans created by #Bean method.
I have also tried using below in Application.properties but still no use.
spring.main.lazy-initialization=true
Also, if you wish, please comment on whether I should use #Component for each Class like I am using or not and what is better practice instead.
I think you misunderstood the meaning of the lazy flag you are passing,
It means that the object will be created only when it is invoked but it does not say that it will not scan that package. Spring will scan all packages and store bean definition names but it will create the objects only when it is invoked, if you have passed the lazy flag to it.
You can verify this behaviour by checking the number of beans created when you pass the lazy flag as true and false.
you can check it as given below
ApplicationContext context = SpringApplication.run(SpringBootApplication.class, args);
System.out.println("count:"+context.getBeanDefinitionCount());
Edit on Apr/7th 2020 start
Another way to do that is create a constructor and use that to inject the autowired properties and print out a log when they enter the constructor.
I did the same in a sample project and below is he result, first one is for eager initialization and next one for lazy.
spring.main.lazy-initialization=false
Application logs
Inside Constructor
calling bean
inside bean method
spring.main.lazy-initialization=true
Application logs
calling bean
Inside Constructor
inside bean method
Edit on Apr/7th 2020 end
Please mark this as answered if I answered your question.
Thank you
Long story short:
For anyone wanting to lazily initialize their whole Spring Boot context, setting this property to true is the way to go:
spring.main.lazy-initialization=true
Pro tip:
It can be used in combination with the #Lazy annotation, set to false; so all the defined beans will use lazy initialization, except for those that we explicitly configure with #Lazy(false).
In such a way, the lazy initialization becomes opt-out instead of the default opt-in.

Why is #Bean(initMethod="") not detecting given method in spring?

Edit Fixed by changing package.
I have this configuration file for spring framework
#Configuration
public class AppConfig {
#Bean(initMethod = "populateCache")
public AccountRepository accountRepository(){
return new JdbcAccountRepository();
}
}
JdbcAccountRepository looks like this.
#Repository
public class JdbcAccountRepository implements AccountRepository {
#Override
public Account findByAccountId(long
return new SavingAccount();
}
public void populateCache() {
System.out.println("Populating Cache");
}
public void clearCache(){
System.out.println("Clearing Cache");
}
}
I'm new to spring framework and trying to use initMethod or destroyMethod. Both of these method are showing following errors.
Caused by: org.springframework.beans.factory.support.BeanDefinitionValidationException: Could not find an init method named 'populateCache' on bean with name 'accountRepository'
Here is my main method.
public class BeanLifeCycleDemo {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new
AnnotationConfigApplicationContext(AppConfig.class);
AccountRepository bean = applicationContext.getBean(AccountRepository.class);
applicationContext.close();
}
}
Edit
I was practicing from a book and had created many packages for different chapters. Error was it was importing different JdbcAccountRepository from different package that did not have that method. I fixed it and it works now. I got hinted at this from answers.
Like you said, if you are mixing configurations types, it can be confusing. Besides, even if you created a Bean of type AccountRepository, because Spring does a lot of things at runtime, it can call your initMethod, even if the compiler couldn't.
So yes, if you have many beans with the same type, Spring can be confused an know which one to call, hence your exception.
Oh and by the way, having a Configuration creating the accountRepoisitory Bean, you can remove the #Repository from your JdbcAccountRepository... It is either #Configuration + #Bean or #Component/Repository/Service + #ComponentScan.
TL;DR
Here is more information and how Spring creates your bean : What object are injected by Spring ?
#Bean(initMethod = "populateCache")
public AccountRepository accountRepository(){
return new JdbcAccountRepository();
}
With this code, Spring will :
Detect that you want to add a Bean in the application Context
The bean information are retrieved from the method signature. In your case, it will create a bean of type AccountRepository named accountRepository... That's all Spring knows, it won't look inside your method body.
Once Spring is done analysing your classpath, or scanning the bean definitions, it will start instanciating your object.
It will therefor creates your bean accountRepository of type AccountRepository.
But Spring is "clever" and nice with us. Even if you couldn't write this code without your compiler yelling at you, Spring can still call your method.
To make sure, try writing this code :
AccountRepository accountRepository = new JdbcAccountRepository();
accountRepository.populateCache(); // Compiler error => the method is not found.
But it works for Spring... Magic.
My recommandation, but you might thinking the same now: If you have classes across many packages to answer different business case, then rely on #Configuration classes. #ComponentScan is great to kickstart your development, but reach its limit when your application grows...
You mix two different ways of spring bean declaration:
Using #Configuration classes. Spring finds all beans annotated with #Configuration and uses them as a reference to what beans should be created.
So if you follow this path of configuration - don't use #Repository on beans. Spring will detect it anyway
Using #Repository - other way around - you don't need to use #Configuration in this case. If you decide to use #Repository put #PostConstruct annotation on the method and spring will call it, in this case remove #Configuration altogether (or at least remove #Bean method that creates JdbcAccountRepository)
Annotate populateCache method with #PostConstruct and remove initMethod from #Bean. It will work.

Could not autowire. No beans of 'MessagingPropertiesRefactor' type not found

I've seen other questions related to this issue but none of them actually helps with my issue.
I have these two properties defined in my test class.
#Autowired
private MessagingProperties messagingProperties;
#Autowired
private MessagingPropertiesRefactor messagingPropertiesRefactor;
I am trying to create a new version of MessagingProperties.java. I basically copied this class and create a new file MessagingPropertiesRefactor.java (same package/dir) and pasted the same code. I changed the class definition, etc., but for the most part are the same.
I get an IntelliJ design time compiler error stating that "Could not autowire. No beans of 'MessagingPropertiesRefactor' type not found."
I then searched for every single Usage of the original class to double check if it has been declared somewhere but I have found nothing.
I am "new" to Java (and Spring). Has anyone run into the same issue before?
If your new class MessagingPropertiesRefactor is not annotated with #Component you have got to declare it either in beans.xml like this:
<beans>
<bean name="messagingPropertiesRefactor" class="com.package.path.MessagingPropertiesRefactor"/>
</beans>
or in your AppConfig.java like this:
#Configuration
public class AppConfig {
#Bean
public MessagingPropertiesRefactor messagingPropertiesRefactor() {
return new MessagingPropertiesRefactor();
}
}
Source Reference
If you want to apply Spring dependency injection in tests, you have 2 basic options:
If you want to have the beans declared in XML, declare both MessagingProperties and MessagingPropertiesRefactor in XML file and annotate the test class the following way:
#RunWith(SpringRunner.class)
#ContextConfiguration("your.xml")
The beans should be successfully autowired.
To have the beans declared in JavaConfig, do the following
2.1. Annotate you test class like this:
#RunWith(SpringRunner.class)
#ContextConfiguration
2.2. Inside the test class, define context configuration class that declates the beans that you need:
#Configuration
static class Config {
#Bean
public MessagingProperties messagingProperties() {
// Assuming MessagingProperties has default ctor.
return new MessagingProperties();
}
// Same for MessagingPropertiesRefactor
}
Enjoy the autowired beans :)
*The config class does not have to be nested into the test class.
For more info regarding the topic, please consult Spring documentation: https://docs.spring.io/spring/docs/current/spring-framework-reference/testing.html#testcontext-ctx-management-javaconfig, Chapter 3.5.4. Context management.
Ensure that MessagingPropertiesRefactor has all annotations applied to the class that MessagingProperties has. If it has, than look for the bean definition of MessagingProperties in xml configurations for your project and make a copy.
So, I found the "magic" line of code that makes it a "bean".
#EnableConfigurationProperties({MessagingProperties.class, MessagingPropertiesRefactor.class})
public class MessagingConfiguration {
#Autowired
private MessagingProperties messagingProperties;
#Autowired
private MessagingPropertiesRefactor messagingProperties;
So, apparently all I needed to do is add this class to the #EnableConfigurationProperties attribute. Then I can use it anywere by using the #Autowired attribute.
Now... why or how, I don't know (like I said, I am "new" to java) and I would love for someone to elaborate on this.

Spring 3, risks of configurable annotation for injecting beans in un-managed classes?

I have a Spring 3 project which acts as a Rest API, and wanted to wire a spring bean I have into an unmanaged class for logging purposes.
After trying many different things, what worked was marking my unmanaged class with the annotation #Configurable.
Like:
#Configurable
public class ClassNotManagedBySpring {
#Autowired
#Qualifier("myBean")
private MyBean myBean;
}
#Service("myBean")
public class MyBean {
#Autowired
#Qualifier("someOtherBean")
private SomeOtherBean someOtherBean;
}
And then in my beans.xml:
<context:spring-configured/>
So now let's say that ClassNotManagedBySpring.java, is one of 6 classes that all do something similar, except 3 of them ARE managed by spring because they have the #Component annotation.
But all 6 of these classes need to #Autowire MyBean.java and only some need the #Configurable annotation.
To note, I was already previously using AspectJ in this app for multiple other purposes.
I want to know what is the risk in my spring application by all of a sudden wiring spring managed dependencies into un managed classes in this way?
Can there be performance issues? Risks of errors at runtime?
If this isn't the best way of wiring a spring managed bean into an unmanaged class, what is?
I've been using #Configurable for years without issues, it's a very easy solution if you need app instantiated beans configured by Spring. My use cases were all in the UI tier. I also used #Configurable(preConstruction = true) whenever I needed autowired values already in the constructor. Of course, if you make millions of #Configurable objects it might be a performance issue, otherwise I wouldn't worry too much about it. The only small aesthetic problem I had was Eclipse giving me some red underlines at class definitions extending #Configurable classes, complaining that the hierarchy of class SomeClass is inconsistent, but it compiled them nevertheless, no errors in the Problems view or at runtime whatsoever.

Specify order to Spring #Autowired

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

Categories