im gettting the following error
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionCont
You annotated your Dao class with @Transactional, but not your service class. The line:
Visitor storedVisitor =
(Visitor) sessionFactory.getCurrentSession().get(Visitor.class,
visitorDetails.getTfscNumber(), LockMode.NONE);
requires you to be in a transaction.
You can fix this by adding the @Transactional annotation to your ProfileService class, or just the registerVisitor() method.
I solved the above problem by following two step
1-Adding @Transactional support in my service method which is calling DAO methods
2-By importing the applicationContext.xml in spring-servlet.xml in this way
<import resource="applicationContext.xml" />
<mvc:annotation-driven />
<context:component-scan base-package="com.json.api.*" />
<!--Third Party Integration should be injected in xml start here -->
<bean id="integrationInterface" class="com.json.api.IntegerationInterface"></bean>
<!--Third Party Integration should be injected in xml start here -->
<mvc:interceptors>
<bean id="apiServiceInterceptor" class="com.json.api.interceptor.ApiServiceInterceptor"></bean>
</mvc:interceptors>
<!--To Enable @Value to map key with provided fields for property files -->
<context:property-placeholder />
It removes the need to scan packages in two places spring-servlet.xml and applicationContext.xml
I know this is an question with some age, but I ran into this issue and found that if you are using Spring-Java configuration, that a resolution had a couple parts to this. Relative placement of some configuration to the controller was important.
First, the CoreConfiguration
@Configuration
public class CoreConfiguration {
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean factoryBean = new org.springframework.orm.hibernate4.LocalSessionFactoryBean();
String annotatedPckgs[] ={"org.tigersndragons.reports.model.warehouse"};
factoryBean.setAnnotatedPackages(annotatedPckgs);
Properties hibernateProperties = new Properties();
try {
hibernateProperties.load(this.getClass().getResourceAsStream("props/hibernate.properties"));
factoryBean.setHibernateProperties(hibernateProperties);
} catch (IOException e) { }
factoryBean.setPackagesToScan("org.telligen.reports.model.warehouse");
factoryBean.setDataSource(warehouseDataSource());//("jdbc/warehouse");
try {
factoryBean.afterPropertiesSet();
} catch (IOException e) { }
return factoryBean;
}
@Bean
public WarehouseDAO getWarehouseDAO(){
WarehouseDAO wrhsDao = new WarehouseDAO();
wrhsDao.setSessionFactory(sessionFactory().getObject());
return wrhsDao;
}
...
@Configuration
public class ScheduleConfiguration {
private static Logger logger = LoggerFactory.getLogger(ScheduleConfiguration.class);
@Autowired
private CoreConfiguration coreConfiguration;
@Bean
public HandlerMapping handlerMapping(){
DefaultAnnotationHandlerMapping mapping = new DefaultAnnotationHandlerMapping();
mapping.setInterceptors(new Object []{coreConfiguration.openSessionViewInterceptor()});
return mapping;
}
@Bean
public HandlerAdapter handerAdapter(){
return new AnnotationMethodHandlerAdapter();
}
@Bean
public ScheduleController scheduleController() throws Exception{
ScheduleController controller = new ScheduleController();
controller.setWrhsDao(coreConfiguration.getWarehouseDAO());
return controller;
}
...
In the Controller, I had to set
@Controller
@RequestMapping
public class ScheduleController {
private static Logger logger = LoggerFactory.getLogger(ScheduleController.class);
private WarehouseDAO wrhsDao;
@RenderMapping
@RequestMapping("VIEW")
public String viewSchedule(Map<String, Object> modelMap){...}
public void setWrhsDao(WarehouseDAO wrhsDao) {
this.wrhsDao = wrhsDao;
}
}
The WarehouseDAO has the @Repository annotation and the SessionFactory was not Autowired.
Hope this helps someone else with similar questions.
I solved the same problem with following 2 steps
Placed @Transactional
on the service method as suggested
jordan002 in his answer on this page.
One more thing,If you have 2 configuration files: say
application-context.xml
(For DB and Application Context Specific
configuration) and webmvc-context.xml
(For web/controller specific
configuration), then you should scan the packages different for your
controllers and dao.
The webmvc-context.xml
is loaded after application-context.xml
.
I think the DAO class is loaded first with transactional references
when the application-context.xml is loaded, but it is replace with
another object, without transactional references, when
webmvc-context.xml is loaded.
Any way, I resolve the problem with specific packages scanned:
<context:component-scan base-package="com.app.repository" />
for application-context.xml
and
<context:component-scan base-package="com.app.web" />
for webmvc-context.xml
.
I'll just add something that took me some time to debug : don't forget that a @Transactional annotation will only work on "public" methods.
I put some @Transactional on "protected" ones and got this error.
Hope it helps :)
http://docs.spring.io/spring/docs/3.1.0.M2/spring-framework-reference/html/transaction.html
Method visibility and @Transactional
When using proxies, you should apply the @Transactional annotation only to methods with public visibility. If you do annotate protected, private or package-visible methods with the @Transactional annotation, no error is raised, but the annotated method does not exhibit the configured transactional settings. Consider the use of AspectJ (see below) if you need to annotate non-public methods.
change your DAO 's annotation with @Repository
@Repository
public class ProfileDao {
.
.
.
}
and then make your service method @Transactional for example like this
@Transactional
public List<Retailer> getRetailerByRetailerNumber(String retailerNo) {}