Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SqlSessionFactoryBean falls in circular dependencies by Spring Boot's DataSourceInitializer. #58

Open
izeye opened this issue Feb 22, 2015 · 6 comments

Comments

@izeye
Copy link
Contributor

izeye commented Feb 22, 2015

SqlSessionFactoryBean falls in circular dependencies by Spring Boot's DataSourceInitializer.

With @Lazy annotations it's okay but without them the following exception occurs:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'sqlSessionFactory': Requested bean is currently in creation: Is there an unresolvable circular reference?

A project with @Lazy annotations:
https://github.com/izeye/samples-spring-boot-branches/tree/mybatis-hsqldb

A project without @Lazy annotations:
https://github.com/izeye/samples-spring-boot-branches/tree/mybatis-hsqldb-without-lazy

I guess replacing ApplicationListener<ApplicationEvent> with ApplicationListener<ContextRefreshedEvent> would fix it.

If my usage is incorrect, please let me know.

@dguggi
Copy link

dguggi commented Mar 2, 2015

I can also reproduce this issue with
mybatis-spring-1.2.2, mybatis-3.2.8, spring-boot-1.2.2, spring-4.1.5

My usecase:

  • two SqlSessionFactory(Beans) with two (different) @MapperScan (using spring @configuration classes)

this also leads to the warning message mentioned above:
"Requested bean is currently in creation: Is there an unresolvable circular reference?"

I think the problem is in MapperFactoryBean.java (mybatis-spring) and how it is created via the "ClassPathMapperScanner".

my observations:

  • ClassPathMapperScanner creates "GenericBeanDefinition" (in my case for scanned classes that implement a marker interface)
  • afterwards org.springframework.beans.factory.support.AbstractBeanFactory.getTypeForFactoryBean() is invoked for every created "GenericBeanDefinition" (that is MapperFactoryBean instances)
  • ... which actually invokes MapperFactoryBean.getObjectType() and this method returns null (!) (as the setMapperInterface() method seems not to be invoked yet)

I could fix this (using a patched mybatis-spring version) as follows:

Changes to MapperFactoryBean.java

add constructor that takes the mapperinterface as argument:

public MapperFactoryBean2(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
 }
  • for backward comp. reasons i also added a default constructor:
public MapperFactoryBean2() {
}

Changes to ClassPathMapperScanner.java

Create GenenericBeanDefinition (in doScan() method) using the new constructur (vs. using setMapperInterface() method):

...
        // the mapper interface is the original class of the bean
        // but, the actual class of the bean is MapperFactoryBean  
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
        // NOTE: the line above replaces the line below...
        //definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());
        definition.setBeanClass(MapperFactoryBean2.class);
...

Hope this helps and could make it into the next mybatis-spring release (as this resolved our issue).

emacarron added a commit that referenced this issue Mar 4, 2015
#58 added possibility to apply mapperInterface to MapperFactoryBean via ...
@rupert-madden-abbott
Copy link

I encountered the same issue as dguggi when trying to use @MapperScan with multiple datasources. My solution was to replace this annotation with MapperScannerConfigurer bean.

However, this then causes the @Configuration bean to get initialised too early and, in particular, before autowiring has had a chance to happen. This then prevents injecting Spring's Environment bean so I had to make my @Configuration bean implement EnvironmentAware instead, to get the Environment bean, in order to configure my datasource.

Complete example workaround here: https://gist.github.com/rupert654/8a3af4ae04a9be71481e

@emacarron
Copy link
Member

Does @dguggi's solution fix your case?

@izeye
Copy link
Contributor Author

izeye commented Mar 6, 2015

@emacarron If you're asking to me, I don't think so. I've got the same exception but by different cause.

Mine is caused by ApplicationListener as described above.

@dguggi
Copy link

dguggi commented Jun 20, 2015

in mybatis-spring-1.2.3 the ClasspathMapperScanner still uses:

definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());

instead of

definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());

therefore also with mybatis-1.2.3 still leads to " Bean creation exception on FactoryBean type check: org.springframework.beans.factory.BeanCreationException.."

@emacarron
Copy link
Member

You are right! Seems that a later PR changed that lines back. Sorry!

I will remake the change again in master.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants