Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Spring get circular dependency issues on one machine and not another?

I have a problem getting a Spring Data based application to run in my environment. I am running Debian, but my co-workers are either using Mac or Ubuntu. I have nothing special set up in my environment variables, and am using the exact same version of Java as others.

I have seen this in the logs, suggesting that it is a circular reference problem that is leading to the instantiation failure:

nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'flyway.CONFIGURATION_PROPERTIES': Initialization of bean failed; ... nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'flyway': Requested bean is currently in creation: Is there an unresolvable circular reference? 

So the problem appears to be that flyway needs some dependencies and they need flyway.

The question is, why does this only happen on my environment not anyone elses? Even on the tests using H2 in memory, I see the problem, so its not my database that is at fault.

Is it possible that Spring autowiring is confused somehow, and tries to do things in the wrong order, so that the repository is null when it tries to set it?

Does Spring have a badly implemented topological sort for ordering dependencies?

Why would it misbehave on my environment?

Could ordering of the classpath influence its behaviour?

======================

The application will not start with this error:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contentItemRepository': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: Repository interface must not be null on initialization!     at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBeanRegistrySupport.java:175)     at org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBeanRegistrySupport.java:127)     at org.springframework.beans.factory.support.AbstractBeanFactory.getObjectForBeanInstance(AbstractBeanFactory.java:1517)     at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:251)     at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)     at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1127) 

============================

The ContentItemRepository signature is:

@Repository @Transactional public interface ContentItemRepository extends JpaRepository<ContentItem, String>, JpaSpecificationExecutor<ContentItem> { 

============================

This used to work for me, and I was able to identify the commit that broke the build, by iterating through all commits, doing a mvn clean install, and trying to start the server, until I found the delta that broke it.

The 'contentItemRepository' that cannot be null is this one:

@Component +public class UrlAliasRequestConverter implements Mapper<UrlAliasRequest, UrlAlias> { + +    /** +     * The content item contentItemType repository. +     */ +    @Autowired +    private ContentItemRepository contentItemRepository; 
like image 932
user2800708 Avatar asked Mar 30 '15 13:03

user2800708


People also ask

How can Spring circular dependency be prevented?

4.2. A simple way to break the cycle is by telling Spring to initialize one of the beans lazily. So, 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.

How does Spring determine circular dependency?

Circular dependency in Spring happens when two or more beans require instance of each other through constructor dependency injections. For example: There is a ClassA that requires an instance of ClassB through constructor injection and ClassB requires an instance of class A through constructor injection.

What's wrong with circular dependencies?

and, yes, cyclic dependencies are bad: They cause programs to include unnecessary functionality because things are dragged in which aren't needed. They make it a lot harder to test software. They make it a lot harder to reason about software.

How can circular dependencies be avoided?

Circular dependencies can be introduced when implementing callback functionality. This can be avoided by applying design patterns like the observer pattern.


1 Answers

I've the same issue on Ubuntu 16.04.

I found that the problem with

@ComponentScan(basePackages = "com.my.app") 

The code is running at least 5 different machine (windows, ubuntu 15.04 and ubuntu 16.04 desktop) but doesn't start our CI server (ubuntu 16.04 server).

After I changed

@ComponentScan(basePackages = "com.my.app") 

to

@ComponentScan(basePackages = {"com.my.app.service", "com.my.app.config", "com.my.app"}) 

the code is running on CI server too.

I think this is a Spring issue with beans loader...

UPDATE:

https://github.com/spring-projects/spring-boot/issues/6045

https://jira.spring.io/browse/SPR-14307

like image 112
István Pató Avatar answered Sep 21 '22 04:09

István Pató