I am developing a Java Web application with Spring MVC and Hibernate, I am new to developing with these frameworks and I am trying to list some records but I get the following:
org.hibernate.HibernateException: getCriteriaBuilder is not valid without active transaction
Complete exception:
org.hibernate.HibernateException: getCriteriaBuilder is not valid without active transaction
at org.hibernate.context.internal.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:351)
at com.sun.proxy.$Proxy36.getCriteriaBuilder(Unknown Source)
at com.edwin.spring.dao.PersonDAOImpl.listPersons(PersonDAOImpl.java:34)
at com.edwin.spring.service.PersonServiceImpl.listPersons(PersonServiceImpl.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:333)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy35.listPersons(Unknown Source)
at com.edwin.spring.controllers.PersonController.list(PersonController.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:475)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:625)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:498)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:796)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1372)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Unknown Source)
The exception is thrown in the PersonDAOImpl class in this line
CriteriaBuilder builder = sessionFactory.getCurrentSession().getCriteriaBuilder();
PersonDAOImpl.java
@Repository("personDao")
public class PersonDAOImpl implements PersonDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
public void save(Person person) {
sessionFactory.getCurrentSession().saveOrUpdate(person);
}
@Override
public void delete(Person person) {
sessionFactory.getCurrentSession().delete(person);
}
@Override
public List<Person> listPersons() {
CriteriaBuilder builder = sessionFactory.getCurrentSession().getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> employeeRoot=criteria.from(Person.class);
criteria.select(employeeRoot);
return sessionFactory.getCurrentSession().createQuery(criteria).getResultList();
}
}
It doesn't seem to work because the call is not in a transaction but I use the @Transactional
Spring annotation on the Service:
@Service
@Transactional
public class PersonServiceImpl implements PersonService {
@Autowired
private PersonDAO personDao;
@Override
public void save(Person person) {
personDao.save(person);
}
@Override
public void delete(Person person) {
personDao.delete(person);
}
@Override
public List<Person> listPersons() {
return personDao.listPersons();
}
@Override
public Person getById(Integer id) {
return personDao.getById(id);
}
}
This is the controller
@Controller
@RequestMapping("/persons")
public class PersonController {
private static final Logger logger = LoggerFactory.getLogger(PersonController.class);
@Autowired
private PersonService personService;
@RequestMapping(value = {"/", "/all", "/list"}, method = RequestMethod.GET)
public String list(Model model) {
logger.info("Se ingresa al método de listar personas");
List<Person> persons = personService.listPersons();
logger.info("listando personas, hay un total de " + persons.size());
model.addAttribute("persons", persons.size());
return "persons";
}
}
This is the web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets
and Filters -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
The servlet-contex.xml file
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
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-4.3.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.3.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- DispatcherServlet Context: defines this servlet's request-processing
infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving
up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources
in the /WEB-INF/views directory -->
<beans:bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.edwin.spring" />
<!-- Datasource -->
<context:property-placeholder location="classpath:hibernate.properties" />
<beans:bean
class="org.springframework.jdbc.datasource.DriverManagerDataSource"
id="dataSource">
<beans:property name="driverClassName" value="${jdbc.driver}" />
<beans:property name="url" value="${jdbc.url}" />
<beans:property name="username" value="${jdbc.user}" />
<beans:property name="password" value="${jdbc.password}" />
</beans:bean>
<!--SessionFactory -->
<beans:bean id="hibernateSessionFactory"
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<beans:property name="dataSource" value="#{dataSource}" />
<beans:property name="packagesToScan" value="com.edwin.spring.model" />
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">${hibernate.dialect}</beans:prop>
<beans:prop key="hibernate.connection.pool_size">1</beans:prop>
<beans:prop key="hibernate.show_sql">${hibernate.show_sql}</beans:prop>
<beans:prop key="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory
</beans:prop>
<!--<prop key="hibernate.hbm2ddl.auto">create-drop</prop> -->
<beans:prop key="hibernate.format_sql">true</beans:prop>
<beans:prop key="hibernate.generate_statistics">true</beans:prop>
<beans:prop key="hibernate.use_sql_comments">true</beans:prop>
<beans:prop key="hibernate.current_session_context_class">thread</beans:prop>
<beans:prop key="hibernate.cglib.use_reflection_optimizer">true</beans:prop>
<beans:prop key="hibernate.hibernate.cache.use_query_cache">true</beans:prop>
<beans:prop key="hibernate.enable_lazy_load_no_trans">true</beans:prop>
<beans:prop key="hibernate.transaction.flush_before_completion">true</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<tx:annotation-driven transaction-manager="transactionManager"/>
<beans:bean class="org.springframework.orm.hibernate5.HibernateTransactionManager"
id="transactionManager">
<beans:property name="sessionFactory" ref="hibernateSessionFactory"/>
</beans:bean>
</beans:beans>
And finally the hibernate.properties file that is in src/main/resources
#DB properties:
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring
jdbc.user=root
jdbc.password=1234
#Hibernate Configuration:
hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
hibernate.show_sql=true
hibernate.format_sql=true
I have tried to place the @Transactional
in the method directly and it hasn't worked either, I don't know what is happening or if something is misconfigured, thanks in advance :).
I already saw where the problem is going, in your configuration apart from the "common" you have this
Some are used in JTA configurations, but if we have our factory set to local, we don't need it.
Testing with the configuration if we remove
hibernate.current_session_context_class
it you should not have problems