spring-projects / spring-framework

Spring Framework
https://spring.io/projects/spring-framework
Apache License 2.0
56.62k stars 38.13k forks source link

@ComponentScan don't work for @Repository annotated DAOs using SessionFactory [SPR-8853] #13495

Closed spring-projects-issues closed 12 years ago

spring-projects-issues commented 12 years ago

Dominik Hirt opened SPR-8853 and commented

If using the JavaConfig based app configuration with @Configuration and include the new @ComponentScan annotation for all of my packages, the creation of the application context failed for the DAO's annotated with @Repository which uses Hibernate/SessionFactory with IllegalArgumentException: 'sessionFactory' or 'hibernateTemplate' is required.

A workaround for this error exists: 1) do not use @ComponentScan in the configuration class annotated with @Configuration 2) instead put the component-scan declarations into a single xml file and import this file by using @ImportResource in the app configuration class.

I've created a reproduction project at Github (https://github.com/SpringSource/spring-framework-issues


Affects: 3.1 RC1

Reference URL: http://forum.springsource.org/showthread.php?117204-Strange-behavior-for-ComponentScan-SessionFactory-in-3.1.0RC1

Referenced from: commits https://github.com/spring-projects/spring-framework-issues/commit/25b55a1c4932ed84fea02423c4fabc779b3df1af, https://github.com/spring-projects/spring-framework-issues/commit/dcfeff2be25e2990f83c9637f093c776dd55ca93

spring-projects-issues commented 12 years ago

Rossen Stoyanchev commented

Merged https://github.com/SpringSource/spring-framework-issues/pull/13.

spring-projects-issues commented 12 years ago

Chris Beams commented

Thanks, Dominik! We'll look into this.

spring-projects-issues commented 12 years ago

Chris Beams commented

Hi Dominik,

Everything is actually working as designed here. The problem is that you have default-autowire="byType" specified in your componentScan.xml file. This causes the Spring container to automatically inject the SessionFactory @Bean into your CustomerDAO. However, you have no equivalent configuration on the pure-java AppComponentWithComponentScan side.

You can either explicitly register your CustomerDAO as a @Bean and inject the SessionFactory with a call to the sessionFactory() method, or you can override the setSessionFactory() method in CustomerDAO and mark it as @Autowired. Your choice, but things are working as intended here.

It's worth noting that we don't really recommend use of the HibernateTemplate and HibernateDaoSupport classes anymore. Since Hibernate 3, the API is nice enough to use on its own. Consider dropping use of those classes and just inject the SessionFactory directly into your CustomerDAO class. This is often called "Native Hibernate DAO style".

Also note that Spring 3.1 RC1 includes the new LocalSessionFactoryBuilder class, which is designed for use in @Bean methods. Unlike the *SessionFactoryBean classes you're using right now, it doesn't require calling methods like afterPropertiesSet and getObject. This new builder class lives in the orm.hibernate4 package - so you'll need to upgrade to Hibernate 4.0 CR4 or better to use it. Just FYI.

spring-projects-issues commented 12 years ago

Dominik Hirt commented

Hi Cris,

thank you for your recommendations. I've updated to Hibernate 4.0.0.CR6 and switched to 'native hibernate dao style'. With this new setup I run my DAO unit tests (including a @Bean transactionManager) and stumble upon the same NoSuchMethodError as mentioned in SPS-8776: java.lang.NoSuchMethodError: org.hibernate.SessionFactory.openSession()Lorg/hibernate/classic/Session;

Is there any workaround to proceed without waiting for 3.1RC2 ?

Furthermore, you wrote, that the new LocalSessionFactoryBuilder doesn't require calling methods like afterPropertiesSet and getObject. But how can I get the sessionFactory from that builder without those methods ?

spring-projects-issues commented 12 years ago

Chris Beams commented

Is there any workaround to proceed without waiting for 3.1RC2 ?

Use nightly snapshots. See my comment on #13419 for instructions.

But how can I get the sessionFactory from that builder without those methods ?

Call the buildSessionFactory() method.

spring-projects-issues commented 12 years ago

Dominik Hirt commented

Hi Chris, as you recommend, I switched to using the native Hibernate DAO style, starting with my current setup including Hibernate 3.6.0 Final. After that, I update Hibernate as well (to 4.0.0.CR6) in order to use LocalSessionFactoryBuilder (using the LocalSessionFactoryBean before, therefor my -stupid- last question regarding building the sessionFactory...) With this new setup (nightly snapshots of Spring 3.1 and Hibernate 4.0.0CR6) I got everytime "No session found for current thread" for the same Unit/Integration test which works under Hibernate 3.6.0 I double check all that transactional stuff (@EnableTransactionManagement, @Bean for the TxManager, @Transactional in Service/DAO, using AbstractTransactionalJUnit4SpringContextTests etc.) but my tests failed with "No session found for current thread". At Stackoverflow I found an answer mentioned, that component scan of the transactional beans (my Services/DAO's) and the definition of txManager has to be defined within the same file ! In my case, I've defined componentScan only in XML and all other beans in AppConfig.java. After moving @EnableTransactionManagement to the xml as and define the txManager bean in the xml file too, everythings works again. Therefor it seems, that there are problems with Hibernate4, but I know, you guys work hard on that issue... For me it's still not possible to use 100% JavaConfig only for my setup mentioned above, I need the context configuration splitted into multiple files (Java and XML). I can update the Spring repo project at Github if you need that.

Kind regards Dominik

spring-projects-issues commented 12 years ago

Chris Beams commented

Hi Dominik,

Please create a separate issue for the "No session found for current thread" issue. And yes, please reproduce this with a project under the spring-framework-issues repository. You can just copy your existing #13495 directory and modify it from there.

Please add a comment to this issue mentioning the new issue so that I'm notified immediately.

Please provide a link to the stackoverflow thread you mentioned as well.

Thanks.

spring-projects-issues commented 12 years ago

Dominik Hirt commented

Hi Chris, during preparation of the reproduction project, I found my mistake: I've used two different transaction manager implementations: HibernateTxManager (defined externally in XML) and DataSourceTransactionManager using internally as @Bean. Obviously the latter one doesn't contain the sessionFactory and therefor I've got the error 'No session found....". I fixed my setup in my webapp under development, also putting back the component scan from XML into Java-Config and now everything works fine ! Thank you for all the very helpful hints and recommendations.

spring-projects-issues commented 12 years ago

Chris Beams commented

Excellent! Glad to hear.