EnableTransactionManagement / Transactional: No Session found for current thread
I know, that this question had been asked numerous times, but anyway the given answers didn't help me.
I get the symptomatic error "No Session found for current thread" when calling a service method which is annotated with @Transactional although @EnableTransactionManagement is set.
I had the same problem a year before and ended up with a xml-Configuration. Maybe you can help me.
My setting is as followed:
Code:
public class LifepulseWebAppinitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { LifepulseWebConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
}
As you can see LifepulseWebConfig is given as configuration and it looks like this:
Code:
package com.lifepulse.config;
@Configuration
@EnableWebMvc
@ComponentScan(value= {"com.lifepulse.controllers"})
@EnableTransactionManagement(proxyTargetClass=true, mode=AdviceMode.PROXY)
public class LifepulseWebConfig extends WebMvcConfigurerAdapter implements TransactionManagementConfigurer {
@Autowired
ApplicationContext context;
@Bean
ViewResolver viewResolver(){
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setSuffix(".jsp");
return resolver;
}
@Bean
MainService mainService(){
return new MainServiceImpl();
}
@Bean(name="databaseUrl")
public String getDatabaseUrl(){
return "jdbc:mysql://localhost/db_name";
}
@Bean(name="sessionFactoryProperties")
public Properties getSessionFactoryProperties(){
Properties props = new Properties();
props.put("hibernate.dialect", MySQL5InnoDBDialect.class.getName());
props.put("hibernate.hbm2ddl.auto", "create-drop");
props.put("hibernate.show_sql", "true");
props.put("hibernate.format_sql", "true");
return props;
}
@SuppressWarnings("unchecked")
private static final Class<? extends Serializable>[] ANNOTATED_CLASSES=new Class[]{
Melder.class
};
private static Class<? extends Serializable>[] getAnnotatedClasses(){
return ANNOTATED_CLASSES;
}
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl(getDatabaseUrl());
dataSource.setUsername("bla");
dataSource.setPassword("foo");
return dataSource;
}
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean factory = new LocalSessionFactoryBean();
factory.setAnnotatedClasses(getAnnotatedClasses());
factory.setHibernateProperties(getSessionFactoryProperties());
factory.setDataSource(dataSource());
return factory;
}
@Bean()
public GenericDao genericDao() {
return new HibernateDaoImpl();
}
@Override
public PlatformTransactionManager annotationDrivenTransactionManager() {
System.out.println("1: "+txManager());
return txManager();
}
@Bean
PlatformTransactionManager txManager(){
HibernateTransactionManager htm = new HibernateTransactionManager(sessionFactory().getObject());
System.out.println("2: "+htm);
return htm;
}
@Bean(name="transactionInterceptor")
TransactionInterceptor transactionInterceptor(){
Properties prop = new Properties();
prop.put("save", "PROPAGATION_REQUIRED");
TransactionInterceptor ti = new TransactionInterceptor(txManager(), prop);
return ti;
}
}
The @Bean MainService is annotated with @Transactional as can be seen here:
Code:
package com.lifepulse.services.impl;
@Transactional(readOnly=false, rollbackFor={ServiceException.class})
public class MainServiceImpl implements MainService {
@Autowired private GenericDao dao;
@Override
public void createMelder(Melder melder) throws ServiceException {
dao.create(melder);
}
}
And this is the controller where the service-Method is called:
Code:
@Controller()
@RequestMapping(value="/")
public class MainController {
@Autowired private MainService mainService;
private static int counter = 0;
@RequestMapping(value="")
public String index(){
Melder m = new Melder();
m.setAppName("testName"+(counter++));
m.setValue("A Value");
try {
mainService.createMelder(m);
} catch (ServiceException e) {
e.printStackTrace();
}
return "index";
}
}
And here the StackTrace:
Code:
HTTP ERROR 500
Problem accessing /lifepulse/. Reason:
No Session found for current thread
Caused by:
org.hibernate.HibernateException: No Session found for current thread
at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:978)
at com.ansiworks.persistence.HibernateDaoImpl.create(HibernateDaoImpl.java:57)
at com.ansiworks.lifepulse.services.impl.MainServiceImpl.createMelder(MainServiceImpl.java:18)
at com.ansiworks.lifepulse.controllers.MainController.index(MainController.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:746)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:687)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:735)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:669)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:445)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:138)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:564)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:213)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1054)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:372)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:175)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:988)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:136)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:258)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:109)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97)
at org.eclipse.jetty.server.Server.handle(Server.java:410)
at org.eclipse.jetty.server.HttpChannel.run(HttpChannel.java:245)
at org.eclipse.jetty.server.HttpConnection$1.run(HttpConnection.java:75)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:597)
at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:528)
at java.lang.Thread.run(Thread.java:722)
The application works fine except the transaction-manager stuff.
CGLIB is loaded.
Can anybody help me out?
Greetings tarator