HibernateException: Couldn't obtain transaction-synchronized Session for current thread
Looking at your log I can instantly tell that your transaction settings are wrongly set. That's because there's no TransactionInterceptor
call in your stack trace.
The TransactionInterceptor
is called by your Spring Service proxies when your web controllers call the actual Service methods.
Make sure you use the Spring hibernate4 classes:
org.springframework.orm.hibernate4.HibernateTransactionManager
Don't override
@Transactional
methods, but use a template patterns instead.Try using
JPATransactionManager
instead so you can inject the currentEntityManager
with the@PersistenceContext
annotation instead. This is much more elegant than callingsessionFactory.getCurrentSession()
in every DAO method.
One
You must use @Transactional
for @Service
and @Repository
. It lets Spring apply and create proxies with Transaction support.
In your code your @Service
class has no the @Transacional
either in class level or method level
Second
Where is the class that implements WebApplicationInitializer
?
I see you are extending a class.. Anyway My Point is, where is something like the following:
@Override
public void onStartup(ServletContext container) {
// Create the 'root' Spring application context
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(CentralServerConfigurationEntryPoint.class);
// Manage the lifecycle of the root application context
container.addListener(new ContextLoaderListener(rootContext));
// Create the dispatcher servlet's Spring application context
AnnotationConfigWebApplicationContext dispatcherServlet = new AnnotationConfigWebApplicationContext();
dispatcherServlet.register(CentralWebConfigurationEntryPoint.class);
// Register and map the dispatcher servlet
ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherServlet));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
Where CentralServerConfigurationEntryPoint.class
must only scan components that must work in the server side (@Service
, @Repository
, @Configuration
for Transaction, Hibernate, DataSource etc)
Where CentralWebConfigurationEntryPoint
must only scan components that must work in the client/web side (@Controller
, @Configuration
for Formatters, Tiles, Converters etc)
I dont understand your code about
@Override
protected WebApplicationContext createRootApplicationContext() {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
ConfigurableEnvironment environment = rootContext.getEnvironment();
environment.setDefaultProfiles("production");
PropertyUtil propertyUtil = PropertyUtil.getInstance(environment.getActiveProfiles());
String[] basePackages = propertyUtil.getPropertySplitTrimmed("webapp", "basePackages");
rootContext.scan(basePackages);
return rootContext;
}
@Override
protected WebApplicationContext createServletApplicationContext() {
return new AnnotationConfigWebApplicationContext();
}
My point is: you must have two AnnotationConfigWebApplicationContext
one for the server and web side.
Very short answer for this questions id, you just need to use @Transactional with your dao class, mark your configuration class as @EnableTransactionManagement and create a bean
**@Bean
public PlatformTransactionManager transactionManager() {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(dataSource());
return transactionManager;
}**
Here, if you see the code example available in EnableTransactionManagement annotation, it suggest to use DataSourceTransactionManager instead of HibernateTransactionManager.