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.

  1. Make sure you use the Spring hibernate4 classes:

    org.springframework.orm.hibernate4.HibernateTransactionManager
    
  2. Don't override @Transactional methods, but use a template patterns instead.

  3. Try using JPATransactionManager instead so you can inject the current EntityManager with the @PersistenceContext annotation instead. This is much more elegant than calling sessionFactory.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.