exception - JPA + Spring: UnexpectedRollbackException when Transaction is REQUIRED, REQUIRES_NEW or NESTED -
i'm doing first project spring, jpa, , glassfish 3.1 , i'm having troubles. i've been looking solution week, have found nothing.
i have entity (called role), generalreposiroty general methods access entity, rolerepository implements particular methods role, , service class, calls rolerepository. methods of service class transactional, rollbackexception if propagation property required, requires_new or nested. if propagation mandatory, it's thrown exception saying:
org.springframework.transaction.illegaltransactionstateexception: no existing transaction found transaction marked propagation 'mandatory' @ org.springframework.transaction.support.abstractplatformtransactionmanager.gettransaction(abstractplatformtransactionmanager.java:339) @ org.springframework.transaction.interceptor.transactionaspectsupport.createtransactionifnecessary(transactionaspectsupport.java:262) @ org.springframework.transaction.interceptor.transactioninterceptor.invoke(transactioninterceptor.java:101) @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172) @ org.springframework.aop.framework.cglibaopproxy$dynamicadvisedinterceptor.intercept(cglibaopproxy.java:631) ...
if it's not_supported, never or support, select queries work fine, same rollbackexception if try execute create, update or delete query.
i've debugged select queries, , before throw rollbackexception, query gets result fine, , exception thrown @ end of function. in adition, if entities find() of entitymanager , service method doesn't have @transactional anotation, works fine, if make transactional, crashes same exception.
this happens entities have, use explain problem.
i think there wrong spring configuration, don't know what.
this full trace of exception (in lines there references authenticationsuccesshandler class, because it's call service class from):
warning: standardwrappervalve[default]: pwc1406: servlet.service() servlet default threw exception org.springframework.transaction.unexpectedrollbackexception: jta transaction unexpectedly rolled (maybe due timeout); nested exception javax.transaction.rollbackexception: transaction marked rollback. @ org.springframework.transaction.jta.jtatransactionmanager.docommit(jtatransactionmanager.java:845) @ org.springframework.transaction.support.abstractplatformtransactionmanager.processcommit(abstractplatformtransactionmanager.java:662) @ org.springframework.transaction.support.abstractplatformtransactionmanager.commit(abstractplatformtransactionmanager.java:632) @ org.springframework.transaction.interceptor.transactionaspectsupport.committransactionafterreturning(transactionaspectsupport.java:314) @ org.springframework.transaction.interceptor.transactioninterceptor.invoke(transactioninterceptor.java:116) @ org.springframework.aop.framework.reflectivemethodinvocation.proceed(reflectivemethodinvocation.java:172) @ org.springframework.aop.framework.cglibaopproxy$dynamicadvisedinterceptor.intercept(cglibaopproxy.java:631) @ com.citius.reservas.service.service$$enhancerbycglib$$37b50d4.tryjpafind(<generated>) @ com.citius.reservas.authenticationsuccesshandlerimpl.onauthenticationsuccess(authenticationsuccesshandlerimpl.java:47) ... caused by: javax.transaction.rollbackexception: transaction marked rollback. @ com.sun.enterprise.transaction.javaeetransactionimpl.commit(javaeetransactionimpl.java:428) @ com.sun.enterprise.transaction.javaeetransactionmanagersimplified.commit(javaeetransactionmanagersimplified.java:855) @ com.sun.enterprise.transaction.usertransactionimpl.commit(usertransactionimpl.java:208) @ org.springframework.transaction.jta.jtatransactionmanager.docommit(jtatransactionmanager.java:842) ... 45 more
i have following entity:
@entity @table(name = "roles", catalog = "reservas") @xmlrootelement public class role implements serializable { @id @generatedvalue(strategy = generationtype.identity) private integer id; @notnull @size(min = 1, max = 50) private string name; private static final long serialversionuid = 1l;
genericrepository, general class, implemented repositories:
public class genericrepositoryimpl<t> implements genericrepository<t> { @persistencecontext private entitymanager em; private class<t> type; public genericrepositoryimpl( ){ type t = getclass().getgenericsuperclass(); parameterizedtype pt = (parameterizedtype) t; type = (class) pt.getactualtypearguments()[0]; } @override public t find(object pk) { try{ return em.find(type, pk); }catch(java.util.nosuchelementexception ex){ return null; } } @override public t create(t t) { em.persist(t); em.flush(); em.refresh(t); return t; } @override public list<t> query(query q) { list<t> list= q.getresultlist(); if(list==null) list=new arraylist<t>(); return list; } }
this role repository:
@repository public class rolerepositoryimpl extends genericrepositoryimpl<role> implements rolerepository{ @persistencecontext private entitymanager em; @override public role findbyname(string name) { query q = (query) this.em.createnamedquery("role.findbyname"); q.setparameter("name", name); role r = (role) q.getsingleresult(); return r; } @override public list<role> findall() { query q = (query) this.em.createnamedquery("role.findall"); return this.query(q); } }
the service class:
@service public class service { @autowired private rolerepository rolerepository; @transactional //this throws rollbackexception public void tryjpaempty(){ rolerepository.findbyname("example"); } //this doesn't public role tryjpafind(){ return rolerepository.find(new integer(1)); } }
spring configuration (applicationcontext.xml) is:
<?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:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:p="http://www.springframework.org/schema/p" xsi:schemalocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd "> <context:component-scan base-package="com.***.***" /> <jpa:repositories base-package="com.***.***.repositories" /> <tx:annotation-driven /> <tx:annotation-driven transaction-manager="transactionmanager" /> <context:annotation-config /> <beans> <bean id="entitymanagerfactory" class="org.springframework.orm.jpa.localentitymanagerfactorybean"> <property name="persistenceunitname" value="jpareservas"/> </bean> <bean class="org.springframework.dao.annotation.persistenceexceptiontranslationpostprocessor"/> <bean id="transactionmanager" class="org.springframework.transaction.jta.jtatransactionmanager" > <property name="allowcustomisolationlevels"> <value>true</value> </property> </bean> </beans> </beans>
persistence.xml (i have data source , connection pool created in glassfish server):
<?xml version="1.0" encoding="utf-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="jpareservas" transaction-type="jta"> <provider>org.eclipse.persistence.jpa.persistenceprovider</provider> <jta-data-source>reservas_mysql</jta-data-source> <!--named queries--> <mapping-file>meta-inf/mapping/role.xml</mapping-file> <exclude-unlisted-classes>false</exclude-unlisted-classes> </persistence-unit> </persistence>
and finally, have named queires in xml file, that: select r role r
<named-query name="role.findbyname"> <query>select r role r r.name = :name</query> </named-query>
i'm noob spring , jpa, if know improvements, or changes can do, please tell me.
ok, i've solved changing transaction-type resource_local, @ beggining, glassfish gives me lot of troubles. that's way solved it:
i've add metadata-complete="true" header of web.xml. here explained why necesary:
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0" metadata-complete="true">
i've changed persistence.xml, because resource_local application won't use connection pool of glassfish, have put information database connection:
<persistence-unit name="jpareservas" transaction-type="resource_local"> <provider>org.eclipse.persistence.jpa.persistenceprovider</provider> <mapping-file>meta-inf/mapping/user.xml</mapping-file> <exclude-unlisted-classes>false</exclude-unlisted-classes> <properties> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/reservas"/> <property name="javax.persistence.jdbc.user" value="admin"/> <property name="javax.persistence.jdbc.password" value="adminpassword"/> </properties> </persistence-unit>
and @ end, i've changed applicationcontext.xml (spring configuration), because can't use same entitymanager class resource_local jta:
<bean id="transactionmanager" class="org.springframework.orm.jpa.jpatransactionmanager"> <property name="entitymanagerfactory" ref="entitymanagerfactory" /> </bean>
and that's all. don't know why can't use jta doing before, i've solved it!!! :). thank you!
Comments
Post a Comment