Reputation: 46
Currently I'm making a Spring course on Udemy and I'm having problems with the @Transactional
annotation in the CustomerDAO
class. I'm using Maven and Java 8. It simply doesn't works, here is the response from Tomcat 9:
HTTP Status 500 – Internal Server Error
Type Exception Report
Message Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
Description The server encountered an unexpected condition that prevented it from fulfilling the request.
Exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.persistence.TransactionRequiredException: no transaction is in progress
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1013)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Root Cause
javax.persistence.TransactionRequiredException: no transaction is in progress
org.hibernate.internal.SessionImpl.checkTransactionNeeded(SessionImpl.java:3552)
org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1444)
org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1440)
org.springframework.orm.hibernate5.SessionFactoryUtils.flush(SessionFactoryUtils.java:147)
org.springframework.orm.hibernate5.SpringSessionSynchronization.beforeCommit(SpringSessionSynchronization.java:95)
org.springframework.transaction.support.TransactionSynchronizationUtils.triggerBeforeCommit(TransactionSynchronizationUtils.java:96)
org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerBeforeCommit(AbstractPlatformTransactionManager.java:922)
org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:730)
org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:533)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
net.matbm.springlearn.dao.CustomerDAO$$EnhancerBySpringCGLIB$$6447db19.getCustomers(<generated>)
net.matbm.springlearn.dao.CustomerDAO$HOTSWAPAGENT_$$FastClassBySpringCGLIB$$466694ed.invoke(<generated>)
org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
HotswapSpringCallback_1796692748.intercept(HotswapSpringCallback_1796692748.java)
net.matbm.springlearn.dao.CustomerDAO$HOTSWAPAGENT_$$EnhancerBySpringCGLIB$$feb7e678.getCustomers(<generated>)
net.matbm.springlearn.service.CustomerService.getAllCustomers(CustomerService.java:16)
net.matbm.springlearn.controller.CustomerController.listCustomers(CustomerController.java:26)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:189)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:800)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1038)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:942)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1005)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:897)
javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:882)
javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
Note The full stack trace of the root cause is available in the server logs.
I've already seen another stack overflow posts and none of them helped me solve the issue! Currently this is the second consecutive day I'm struggling with this issue. It simply doesn't works. I already tried to create a servlet-context.xml
to "separate the contexts" but it doesn't solved the issue. Here is the source code related to the project:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
id="WebApp_ID" version="3.1">
<display-name>spring-mvc-demo</display-name>
<!-- Spring MVC Configs -->
<!-- Step 1: Configure Spring MVC Dispatcher Servlet -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Step 2: Set up URL mapping for Spring MVC Dispatcher Servlet -->
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- Add support for component scanning -->
<context:component-scan base-package="net.matbm.springlearn.config"/>
<mvc:default-servlet-handler/>
<mvc:annotation-driven/>
</beans>
net.matbm.springlearn.config.AppConfig.java
package net.matbm.springlearn.config;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.mchange.v2.c3p0.PooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import java.beans.PropertyVetoException;
import java.util.Properties;
@Configuration
@EnableWebMvc
@EnableTransactionManagement
@ComponentScan("net.matbm.springlearn")
public class AppConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
@Bean(destroyMethod = "close")
public PooledDataSource dataSource() throws PropertyVetoException {
ComboPooledDataSource source = new ComboPooledDataSource();
source.setDriverClass("org.postgresql.Driver");
source.setJdbcUrl("jdbc:postgresql://localhost/java");
source.setUser("java");
source.setPassword("java");
source.setMinPoolSize(5);
source.setMinPoolSize(20);
source.setMinPoolSize(3000);
return source;
}
@Bean
public LocalSessionFactoryBean sessionFactory() throws PropertyVetoException {
LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
factoryBean.setDataSource(dataSource());
factoryBean.setPackagesToScan("net.matbm.springlearn.model");
factoryBean.setHibernateProperties(hibernateProperties());
return factoryBean;
}
@Bean
public PlatformTransactionManager transactionManager() throws PropertyVetoException {
HibernateTransactionManager manager = new HibernateTransactionManager();
manager.setSessionFactory(sessionFactory().getObject());
return manager;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("resources/");
}
private Properties hibernateProperties() {
Properties hibernateProperties = new Properties();
hibernateProperties.setProperty("hibernate.dialect", "org.hibernate.dialect.PostgreSQL95Dialect");
hibernateProperties.setProperty("hibernate.show_sql", "true");
hibernateProperties.setProperty("hibernate.hbm2ddl.auto", "create");
return hibernateProperties;
}
}
net.matbm.controller.CustomerController.java
package net.matbm.springlearn.controller;
import net.matbm.springlearn.service.CustomerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/customer")
public class CustomerController {
private final CustomerService customerService;
@Autowired
public CustomerController(CustomerService customerService) {
this.customerService = customerService;
}
@RequestMapping()
public String home() {
return "customer/home";
}
@RequestMapping("/list")
public String listCustomers(Model model) {
model.addAttribute("customers", customerService.getAllCustomers());
return "customer/list-customers";
}
}
net.matbm.service.CustomerService.java
package net.matbm.springlearn.service;
import net.matbm.springlearn.dao.CustomerDAO;
import net.matbm.springlearn.model.Customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CustomerService {
@Autowired
private CustomerDAO customerDAO;
public List<Customer> getAllCustomers() {
return customerDAO.getCustomers();
}
}
net.matbm.dao.CustomerDAO.java
package net.matbm.springlearn.dao;
import net.matbm.springlearn.model.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Repository
public class CustomerDAO {
@Autowired
private SessionFactory sessionFactory;
@Transactional
public List<Customer> getCustomers() {
Session session = sessionFactory.getCurrentSession();
Query<Customer> query =
session.createQuery("from Customer", Customer.class);
return query.getResultList();
}
}
net.matbm.model.Customer.java
package net.matbm.springlearn.model;
import javax.persistence.*;
@Entity
@Table(name = "customer")
public class Customer {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "email")
private String email;
public Customer() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
'}';
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.matbm</groupId>
<artifactId>SpringLearn</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Spring Learn</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>5.1.3.RELEASE</spring.version>
<jdk.version>1.8</jdk.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-orm -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/javax.servlet/servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>3.0-alpha-1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.postgresql/postgresql -->
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.5</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate.validator/hibernate-validator -->
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-core -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.7.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-c3p0 -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-c3p0</artifactId>
<version>5.3.7.Final</version>
</dependency>
</dependencies>
<build>
<finalName>SpringMaven</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<url>http://localhost:8080/manager/text</url>
<server>TomcatServer</server>
<path>/</path>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Thanks in advance.
Upvotes: 0
Views: 3092
Reputation: 60
in service layer you used the the @Autowired Annotation and DAO Layer you used the @Tranjaction annotation so thats why its giving an error.
so use the @Transactional Annotation in service layer and use the @Autowired annotation in DAO Layer
Make change in Service layer shown below
import net.matbm.springlearn.dao.CustomerDAO;
import net.matbm.springlearn.model.Customer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class CustomerService {
@Autowired
private CustomerDAO customerDAO;
@Transactional
public List<Customer> getAllCustomers() {
return customerDAO.getCustomers();
}
}
Make change in DAO layer Shown below
package net.matbm.springlearn.dao;
import net.matbm.springlearn.model.Customer;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Repository
public class CustomerDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
public List<Customer> getCustomers() {
Session session = sessionFactory.getCurrentSession();
Query<Customer> query =
session.createQuery("from Customer", Customer.class);
return query.getResultList();
}
}
Upvotes: 1
Reputation: 46
After changing the CustomerDAO
the transaction started working:
@Repository
public class CustomerDAOImpl implements CustomerDAO {
@PersistenceContext
private EntityManager entityManager;
public List<Customer> getCustomers() {
Query<Customer> query =
(Query<Customer>) entityManager.createQuery("from Customer", Customer.class);
return query.getResultList();
}
}
Using @PersistenceContext
instead of a SessionFactory
resolved the issue. I don't know why.
Upvotes: 0
Reputation: 7624
As per exception looks like your transactionManager config is not correct.
Any specific reason for using PlatformTransactionManager
??
If not use this config
Working config for Transaction usinHibernatete 4 looks like this
@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:persistence-mysql.properties" })
@ComponentScan({ "org.baeldung.spring.persistence" })
public class PersistenceConfig {
@Autowired
private Environment env;
@Bean
public LocalSessionFactoryBean sessionFactory() {
LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
sessionFactory.setDataSource(restDataSource());
sessionFactory.setPackagesToScan(
new String[] { "org.baeldung.spring.persistence.model" });
sessionFactory.setHibernateProperties(hibernateProperties());
return sessionFactory;
}
@Bean
public DataSource restDataSource() {
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
dataSource.setUrl(env.getProperty("jdbc.url"));
dataSource.setUsername(env.getProperty("jdbc.user"));
dataSource.setPassword(env.getProperty("jdbc.pass"));
return dataSource;
}
@Bean
@Autowired
public HibernateTransactionManager transactionManager(
SessionFactory sessionFactory) {
HibernateTransactionManager txManager
= new HibernateTransactionManager();
txManager.setSessionFactory(sessionFactory);
return txManager;
}
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
Properties hibernateProperties() {
return new Properties() {
{
setProperty("hibernate.hbm2ddl.auto",
env.getProperty("hibernate.hbm2ddl.auto"));
setProperty("hibernate.dialect",
env.getProperty("hibernate.dialect"));
setProperty("hibernate.globally_quoted_identifiers",
"true");
}
};
}
}
More details here
Else if you want a solution for PlatformTransactionManager
This might help
Upvotes: 0