JPA + Spring: UnexpectedRollbackException when Transaction is REQUIRED, REQUIRES_NEW or NESTED - spring

I'm doing my first project with Spring, JPA, and GlassFish 3.1 and I'm having some troubles. I've been looking for a solution for a week, but I have found nothing.
I have an Entity (called Role), a GeneralReposiroty with general methods to access any entity, a RoleRepository which implements particular methods about Role, and a Service class, which calls RoleRepository. Methods of Service class are transactional, but I get RollBackException if the propagation property is REQUIRED, REQUIRES_NEW or NESTED. If propagation is MANDATORY, it's thrown an exception saying:
org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:339)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:101)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
...
If it's NOT_SUPPORTED, NEVER or SUPPORT, select queries work fine, but I get the same RollbackException if I try to execute a create, update or delete query.
I've debugged the select queries, and before they throw the RollBackException, the query gets the result fine, and the exception is thrown just at the end of the function. In adition, if I get the Entities with find() of EntityManager and the service method doesn't have the #Transactional anotation, works fine, but if I make it transactional, it crashes with the same exception.
This happens with all entities I have, but I use that to explain the problem.
I think there is something wrong with my Spring configuration, but I don't know what.
This is the full trace of the exception (In some lines there are references to AuthenticationSuccessHandler class, because it's where I call to the service class from):
WARNING: StandardWrapperValve[default]: PWC1406: Servlet.service() for servlet default threw exception
org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Transaction marked for rollback.
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:845)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:662)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:632)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:314)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at com.citius.reservas.service.service$$EnhancerByCGLIB$$37b50d4.tryJPAFind(<generated>)
at com.citius.reservas.AuthenticationSuccessHandlerImpl.onAuthenticationSuccess(AuthenticationSuccessHandlerImpl.java:47)
...
Caused by: javax.transaction.RollbackException: Transaction marked for rollback.
at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:428)
at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:855)
at com.sun.enterprise.transaction.UserTransactionImpl.commit(UserTransactionImpl.java:208)
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:842)
... 45 more
I have the 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, a general class, which is implemented by all the 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 is the 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 a 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 a data source and a connection pool created in my 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, I have named queires in a xml file, like that:
SELECT r FROM Role r
<named-query name="Role.findByName">
<query>SELECT r FROM Role r WHERE r.name = :name</query>
</named-query>
I'm really noob with Spring and JPA, so if you know some improvements, or changes I can do, please tell me.

Ok, I've solved it changing transaction-type to RESOURCE_LOCAL, but at the beggining, Glassfish gives me a lot of troubles. That's the way I solved it:
I've add metadata-complete="true" to the header of web.xml. Here is explained why is this 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 my persistence.xml, because with RESOURCE_LOCAL the application won't use the connection pool of Glassfish, I have to put information about 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 at the end, I've changed the applicationContext.xml (Spring configuration), because I can't use the same EntityManager class with RESOURCE_LOCAL as with JTA:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="EntityManagerFactory" />
</bean>
And that's all. I don't know why I can't use JTA like I was doing before, but I've solved it!!! :). Thank you!

Related

Unable to delete row : TransactionRequiredException: Executing an update/delete query

There are several posts on this question but still not getting the solution.
This the parent class Userr.
In a #OneToMany relationship I want to remove a particular child Account.
Now When I do this by "DELETE" query I am getting following exception.
org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete query; nested exception is javax.persistence.TransactionRequiredException: Executing an update/delete query
#RooJavaBean
#RooToString
#RooJpaEntity
#RooJpaActiveRecord(finders = { "findUserrsByUserName"})
public class Userr {
#NotNull
#Column(unique = true)
private String userName;
#NotNull
private int userType;
#OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
private List<Account> accounts = new ArrayList<Account>();
}
Child class
#RooJavaBean
#RooToString
#RooJpaActiveRecord
#RooJpaEntity
public class Account {
#OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<Message> messages = new ArrayList<Message>();
/*#OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<PremiumPlayPositionCombination> premiumPlayPosition = new ArrayList<PremiumPlayPositionCombination>();*/
#OneToMany(mappedBy="account", fetch=FetchType.LAZY, cascade = CascadeType.ALL)
List<PositionCombinationArc> allPositionsArc = new ArrayList<PositionCombinationArc>();
#ManyToOne
#JoinColumn(name="user_id")
private Userr user;
}
Here is my delete query
#Transactional
public static void deleteClientByClientId(Long clientId) {
System.out.println("Delete query findUsersClientsByUser" + clientId);
int deleteCount= entityManager().createQuery("DELETE FROM Account where id =:clientId").setParameter("clientId", clientId).executeUpdate();
System.out.println("Delete query findUsersClientsByUser" + deleteCount);
}
I have added in ApplicationContext-security.xml like this
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<!--
This will automatically locate any and all property files you have
within your classpath, provided they fall under the META-INF/spring
directory. The located property files are parsed and their values can
then be used within application context files in the form of
${propertyKey}.
-->
<context:property-placeholder location="classpath*:META-INF/spring/*.properties"/>
<!--
Turn on AspectJ #Configurable support. As a result, any time you
instantiate an object, Spring will attempt to perform dependency
injection on that object. This occurs for instantiation via the "new"
keyword, as well as via reflection. This is possible because AspectJ
is used to "weave" Roo-based applications at compile time. In effect
this feature allows dependency injection of any object at all in your
system, which is a very useful feature (without #Configurable you'd
only be able to dependency inject objects acquired from Spring or
subsequently presented to a specific Spring dependency injection
method). Roo applications use this useful feature in a number of
areas, such as #PersistenceContext injection into entities.
-->
<context:spring-configured/>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="${database.username}"/>
<property name="password" value="${database.password}"/>
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="transactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="smtp.gmail.com"/>
<property name="port" value="587"/>
<property name="username" value="noreply#uforic.in"/>
<property name="password" value="noreply#123"/>
<property name="javaMailProperties">
<props>
<prop key="mail.transport.protocol">smtp</prop>
<prop key="mail.smtp.auth">true</prop>
<prop key="mail.smtp.starttls.enable">true</prop>
<prop key="mail.debug">true</prop>
</props>
</property>
</bean>
<!--
This declaration will cause Spring to locate every #Component,
#Repository and #Service in your application. In practical terms this
allows you to write a POJO and then simply annotate the new POJO as an
#Service and Spring will automatically detect, instantiate and
dependency inject your service at startup time. Importantly, you can
then also have your new service injected into any other class that
requires it simply by declaring a field for your service inside the
relying class and Spring will inject it. Note that two exclude filters
are declared. The first ensures that Spring doesn't spend time
introspecting Roo-specific ITD aspects. The second ensures Roo doesn't
instantiate your #Controller classes, as these should be instantiated
by a web tier application context. Refer to web.xml for more details
about the web tier application context setup services.
Furthermore, this turns on #Autowired, #PostConstruct etc support. These
annotations allow you to use common Spring and Java Enterprise Edition
annotations in your classes without needing to do any special configuration.
The most commonly used annotation is #Autowired, which instructs Spring to
dependency inject an object into your class.
-->
<context:component-scan base-package="com.uforic.optionstrader">
<context:exclude-filter expression=".*_Roo_.*" type="regex"/>
<!--context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/-->
</context:component-scan>
You can check following things in your code:
If you are using spring based transaction then make sure you import org.springframework.transaction.annotation.Transactional class for #Transactional annotation
In your case it might be javax.transaction.Transactional
I see deleteClientByClientId method in your code as static. #Transactional in spring does not have support for static methods. Make your method non static which is annotated as transactional.
You can refer #Transactional with static method
Let me know, which option works for you.
In Spring context file you need to add below code:
<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:tx="http://www.springframework.org/schema/tx"
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.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<tx:annotation-driven />
Also, add your spring security bean configuration.
When trying to update/delete using Hibernate, it is mendatory to surround the query by a transaction Begin() and Commit() example :
EntityTransaction tr=em.getTransaction();
tr.begin();
Query query = (Query) em.createQuery( "update etudiant set email= :em, adresse= :adr,telephone= :tele,password= :pwd"
+ " where email= :mail");
query.setParameter("em", email)
.setParameter("adr", adresse)
.setParameter("tele", tele)
.setParameter("pwd", pass)
.setParameter("mail", ancienEmail);
int a= query.executeUpdate();
tr.commit();

migrate hibernateTemplate to JPA 2 (executeWithNativeSession - doInHibernate)

I am migrating my code from hibernate 3 (that is using hibernate template) to JPA 2. My project is using Spring as well.
Current project is using hibernatetempate as
hibernateTemplate.executeWithNativeSession(new HibernateCallback<Object>() {
#Override
public Object doInHibernate(Session session) throws SQLException {
Query query = session.getNamedQuery("updateToProcessed");
query.setParameter("Id", id);
return query.executeUpdate();
}
});
updateToProcessed is a simple update hql query. Please help to let me know how to convert it to JPA (to use entityManager)
I tried using
Query query = entityManager.createNamedQuery("updateToProcessed");
query.setParameter("Id", id);
query.executeUpdate();
Complete method is
#Override
public void updateAllBatchDetails(final String id) {
Query query = entityManager.createNamedQuery("updateToProcessed");
query.setParameter("Id", id);
query.executeUpdate();
}
But I am getting error as:
Caused by: javax.persistence.TransactionRequiredException: Executing an update/delete query
at org.hibernate.jpa.spi.AbstractQueryImpl.executeUpdate(AbstractQueryImpl.java:71)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:333)
at com.sun.proxy.$Proxy143.executeUpdate(Unknown Source)
I have configured transactionManager in applicationContext.xml like
I was expecting this answer and I have already configured that in applicationContext.xml but still I am getting that error
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>
But somehow #Transactional is working that I don't want to use.
This is the applicationContext.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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<context:component-scan base-package="com.batch"/>
<context:annotation-config/>
<context:spring-configured/>
<context:property-placeholder location="classpath:batch.properties"/>
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
p:entityManagerFactory-ref="entityManagerFactory"/>
<aop:aspectj-autoproxy/>
<import resource="classpath:core/applicationContext.xml"/>
<import resource="classpath:spring/applicationContext-resources.xml"/>
<import resource="classpath:spring/applicationContext-batch.xml"/>
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:persistenceUnitName="default"
p:jpaVendorAdapter-ref="jpaVendorAdapter"
p:dataSource-ref="dataSource" />
<bean id="batchProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"
p:location="classpath:batch.properties"/>
</beans>
To execute a bulk update you should do like below:
final String updateQuery = "update Person p SET p.name = 'Other Name'";
final int update = entityManager.createQuery(updateQuery).executeUpdate();
System.out.println("updated rows " + update);
Spring will handle the commit for you. [=
Edit: Caused by: javax.persistence.TransactionRequiredException
Have you configured the Transaction? To execute a update you must open a transaction.
With Spring you could use the annotation #Transactional in the method.
For this problem use a Tasklet where you execute your query.
Configure a step using a TaskletStep and you can set 'transaction manager' as well as 'transaction attributes' and errors should go away.

Using tx:annotation-driven prevents Autowiring a bean

I'm developing a module on an OSGi application, using Spring MVC and Virgo Webserver.
On my module I have a Controller, that access a Manager, which has a list of handlers that are responsible for handling report generation.
Everything was doing fine until I had to call a transactional method from an external service. Since none of my classes were transactional I had to add the references to the transation manager and annotation-driven. Then, my Manager stopped being notified.
I understand that when using annotation-driven all my beans must implement a public interface in order for the proxying mechanism to work. And as far as I know, all the classes are (one of them wasn't, but then I changed it).
My configuration files are:
bundle-context.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<context:annotation-config />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="reportManager" class="reportmodule.manager.impl.ReportManagerImpl"/>
<bean id="mvpepReportHandler" class="reportmodule.manager.impl.MVPEPReportHandler"/>
<bean id="reportConfigDao" class="reportmodule.repository.impl.ReportConfigurationHibernateDAOImpl"/>
<bean id="oSGIChangeReportHandler" class="reportmodule.osgi.impl.OSGIChangeReportHandlerImpl"/>
<bean id="reportController"
class="reportmodule.controller.impl.ReportControllerImpl"/>
<bean id="reportControllerHandlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<value>/module/reportController/**=reportController</value>
</property>
<property name="alwaysUseFullPath" value="true"></property>
</bean>
</beans>
and my bundle-osgi.xml is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xmlns:osgi-compendium="http://www.springframework.org/schema/osgi-compendium"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/osgi
http://www.springframework.org/schema/osgi/spring-osgi.xsd
http://www.springframework.org/schema/osgi-compendium
http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium-1.2.xsd">
<osgi:reference id="transactionManager" interface="org.springframework.transaction.PlatformTransactionManager" />
<osgi:reference id="sessionFactory" interface="org.hibernate.SessionFactory" />
<osgi:reference id="smaCoreUtilService" interface="core.util.service.SmaCoreUtilService" />
<osgi:service ref="reportControllerHandlerMapping"
interface="org.springframework.web.servlet.HandlerMapping"
context-class-loader="service-provider"
auto-export="interfaces"/>
<osgi:service interface="reportmodule.api.manager.ReportManager" ref="reportManager" auto-export="interfaces"/>
<osgi:service interface="reportmodule.api.manager.ReportHandler" ref="mvpepReportHandler" auto-export="interfaces"/>
<osgi:service interface="reportmodule.repository.ReportConfigurationDAO" ref="reportConfigDao" auto-export="interfaces"/>
<osgi:service interface="reportmodule.osgi.OSGIChangeReportHandler" ref="oSGIChangeReportHandler" auto-export="interfaces"/>
<osgi:list cardinality="0..N" id="reportHandler" interface="reportmodule.api.manager.ReportHandler" greedy-proxying="true">
<osgi:listener ref="oSGIChangeReportHandler" bind-method="register" unbind-method="unregister"/>
</osgi:list>
</beans>
So, after all the services are being published the oSGIChangeReportHandler.register is called (I'm able to debbug it):
#Service(value="oSGIChangeReportHandler")
public class OSGIChangeReportHandlerImpl implements OSGIChangeReportHandler {
private ReportManager reportManager;
/**
* #param reportManager the reportManager to set
*/
#Autowired
public void setReportManager(ReportManager reportManager) {
this.reportManager = reportManager;
}
#SuppressWarnings("rawtypes")
public void register(ReportHandler reportHandler, Map properties) {
reportManager.addReportHandler(reportHandler);
}
#SuppressWarnings("rawtypes")
public void unregister(ReportHandler reportHandler, Map properties) {
reportManager.removeReportHandler(reportHandler);
}
}
And although the debugger shows Proxies for both the reportManager and reportHandler on the register method, the debugger does not halts on the ReportManagerImpl.addReportHandler method:
#Service(value="reportManager")
#Transactional(propagation = Propagation.MANDATORY, rollbackFor = Exception.class)
public class ReportManagerImpl implements ReportManager {
private ReportConfigurationDAO reportConfigurationDAO;
private ArrayList<ReportHandler> reportHandlers = new ArrayList<ReportHandler>();
/**
* #param reportConfigurationDAO the reportConfigurationDAO to set
*/
#Autowired
public void setReportConfigurationDAO(ReportConfigurationDAO reportConfigurationDAO) {
this.reportConfigurationDAO = reportConfigurationDAO;
}
#Override
#Transactional
public InputStream gerarRelatorio(ReportRequest repoReq) throws NegocioException {
// Generates the report...
}
/* (non-Javadoc)
* #see reportmodule.api.manager.ReportManager#addReportHandler(reportmodule.api.manager.ReportHandler)
*/
#Override
public void addReportHandler(ReportHandler handler) {
if (handler != null) {
this.reportHandlers.add(handler);
}
}
/* (non-Javadoc)
* #see reportmodule.api.manager.ReportManager#removeReportHandler(reportmodule.api.manager.ReportHandler)
*/
#Override
public void removeReportHandler(ReportHandler handler) {
if (handler != null) {
this.reportHandlers.remove(handler);
}
}
}
I must stress that when I remove the tx:annotation-driven tag from the bundle-context.xml file, everything works fine (the handler is properly added to the list during startup).
So, what am I missing here?
Problem solved!
As you can see on my code above, I was defining the beans both via XML and Annotation, thus every bean was duplicated in runtime. Then, when I added the tx:annotation-driven tag the application begun intercepting the wrong bean. It was indeed notifying a bean, but an orphan bean.
HereĀ“s an example working with tx. Look this line:
xmlns:tx="http://www.springframework.org/schema/tx"
and this on schemaLocation:
http://www.springframework.org/schema/tx/spring-tx.xsd
Source:
http://www.springbyexample.org/examples/hibernate-transaction-annotation-config.html

about a BeanCurrentlyInCreationException, unresolvable circular reference

Good afternoon, I have a project based on apache-cxf v 2.5.2, spring 2.5.6 and hibernate v v 3.2.1. I'm using annotations to mark the units and objects I persist and am having a problem when deploying the war. Giving me the following exception:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'storeService': Can not resolve reference to bean 'storeService' while setting constructor argument; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'storeService': Requested bean is Currently in creation: is there an unresolvable loop reference?
this is the applicationContext.xml file
<?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:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
">
<context:component-scan base-package="com.aironman.core" />
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:hibernate.properties"/>
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${database.driverClassName}"/>
<property name="url" value="${database.url}"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="hibernateProperties">
<value>
hibernate.dialect=${database.hibernate.dialect}
hibernate.cache.provider_class=org.hibernate.cache.HashtableCacheProvider
hibernate.show_sql=true
hibernate.use_sql_comments=true
hibernate.jdbc.batch_size=0
hibernate.hbm2ddl.auto=create-drop
hibernate.default_schema=${hibernate.default_schema}
hibernate.generate_statistics=true
hibernate.cache.use_structured_entries=true
</value>
</property>
<property name="annotatedClasses">
<list>
<value>com.aironman.core.pojos.Usuario</value>
<value>com.aironman.core.pojos.Item</value>
<value>com.aironman.core.pojos.Persona</value>
</list>
</property>
</bean>
</beans>
this is beans.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:jaxws="http://cxf.apache.org/jaxws"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">
<import resource="classpath:META-INF/cxf/cxf.xml" />
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />
<!-- DECLARACION DE LOS ENDPOINTS DE LOS WEB SERVICES-->
<jaxws:endpoint
id="storeService" implementor="#storeService"
implementorClass="com.aironman.core.cxf.service.StoreServiceImpl"
address="/Store" />
</beans>
both files are included on web.xml
this is implementation end point web service, storeService:
**#Service("storeService")
#WebService(endpointInterface = "com.aironman.core.cxf.service.StoreService")
public class StoreServiceImpl implements StoreService** {
private Log log = LogFactory.getLog(StoreServiceImpl.class);
#Autowired
#Qualifier("servicioUsuarios")
private ServicioUsuarios servicioUsuarios;
#Autowired
#Qualifier("servicioItems")
private ServicioItems servicioItems;
#Autowired
#Qualifier("servicioApuntes")
private ServicioApuntesContables servicioApuntesContables;
[B]public StoreServiceImpl()[/B]{
log.info("CONSTRUCTOR SIN tipo StoreServiceImpl...");
}
some methods... getters and setters ...
}
this is ServicioUsuariosImpl file:
package com.aironman.core.service;
**#Service("servicioUsuarios")
public class ServicioUsuariosImpl implements ServicioUsuarios** {
private static ConcurrentHashMap <String,Usuario>hashMapUsuarios = new ConcurrentHashMap <String,Usuario> () ;
private Log log = LogFactory.getLog(ServicioUsuariosImpl.class);
#Autowired
#Qualifier("servicioEncriptacion")
private ServicioEncriptacion servicioEncriptacion;
#Autowired
#Qualifier("servicioPersistenciaUsuarios")
private ServicioPersistenciaUsuarios servicioPersistenciaUsuarios;
public ServicioUsuariosImpl(){
log.info("Constructor SIN tipo ServicioUsuariosImpl...");
//TODO pendiente cargar el mapa con una llamada al servicioPersistencia
}
#PostConstruct
public void init()
{
log.info("init method on ServicioUsuariosImpl. Initializing hashMap...");
//i need to call persistence layer to fill the hashMap
}
some methods, getters and setters
}
As you can see, this service has inyected a persistent service called servicioPersistenciaUsuarios, which basically uses a dao marked as #repository.
this is ServicioPersistenciaUsuariosImpl implementation file:
package com.aironman.core.service;
**#Service("servicioPersistenciaUsuarios")
public class ServicioPersistenciaUsuariosImpl implements ServicioPersistenciaUsuarios** {
#Autowired
#Qualifier("usuarioHibernateDao")
private UsuarioHibernateDao usuarioHibernateDao;
private Log log = LogFactory.getLog(ServicioPersistenciaUsuariosImpl.class);
public ServicioPersistenciaUsuariosImpl()
{
log.info("Constructor ServicioPersistenciaUsuariosImpl...");
}
some methods, getters and setters
}
this is usuarioHibernateDao implementation file:
package com.aironman.core.hibernate;
**#Repository
public class UsuarioHibernateDao extends HibernateGenericDao<Usuario, String> implements UsuarioDao**
{
private Log log = LogFactory.getLog(UsuarioHibernateDao.class);
[B]#Autowired
public UsuarioHibernateDao(#Qualifier("sessionFactory") SessionFactory sessionFactory) [/B]{
super(sessionFactory);
}
some methods...
}
ServicioUsuariosImpl has another dependencie, servicioEncriptacion, and as you may see, this is the implementation:
package com.aironman.core.service;
#Service("servicioEncriptacion")
public class ServicioEncriptacionImpl implements ServicioEncriptacion
{
private static final String algoritmo = "SHA-256";
private Log log = LogFactory.getLog(ServicioEncriptacionImpl.class);
private static java.security.MessageDigest diggest ;
[B]public ServicioEncriptacionImpl()[/B]
{some code...
}
some methods...
}
this is ServicioItemsImpl implementation file, another dependencie belongs to StoreServiceImpl.
package com.aironman.core.service;
**#Service("servicioItems")
public class ServicioItemsImpl implements ServicioItems**{
private static final ConcurrentHashMap
<String,com.aironman.core.pojos.Item>
//La pk es el isbn del item
hashMapItems = new ConcurrentHashMap<String,com.aironman.core.pojos.Item>() ;
private Log log = LogFactory.getLog(ServicioItemsImpl.class);
#Autowired
#Qualifier("servicioPersistenciaItems")
private ServicioPersistenciaItems servicioPersistenciaItems;
[B]public ServicioItemsImpl()[/B]
{
log.info("Constructor SIN TIPO ServicioItemsImpl");
}
[B]#PostConstruct
public void init()[/B]
{
log.info("init method on ServicioItemsImpl. Initializing hashMap...");
}
some methods, getters and setters
}
this is servicioPersistenciaItems implementation file:
package com.aironman.core.service;
#Service("servicioPersistenciaItems")
public class ServicioPersistenciaItemsImpl implements ServicioPersistenciaItems
{
#Autowired
#Qualifier("itemHibernateDao")
private ItemHibernateDao itemHibernateDao;
private Log log = LogFactory.getLog(ServicioPersistenciaItemsImpl.class);
[B]public ServicioPersistenciaItemsImpl()[/B]
{
log.info("Constructor SIN tipo ServicioPersistenciaItemsImpl...");
}
some methods, getters and setters...
}
and finish, ServicioApuntesContablesImpl implementation file, with no dependencies
package com.aironman.core.service;
[B]#Service("servicioApuntes")
public class ServicioApuntesContablesImpl implements ServicioApuntesContables[/B]{
private Log log = LogFactory.getLog(ServicioApuntesContablesImpl.class);
private static ConcurrentHashMap <ClaveApunteContable,ApunteContable> mapaApuntesContables
= new ConcurrentHashMap <ClaveApunteContable,ApunteContable> ();
//TODO al final tendre que persistir los apuntes contables, por ahora los mantendre en memoria...
[B]public ServicioApuntesContablesImpl()[/B]
{}
some methods
}
in short, the problem is happening when Spring tries to instantiate the endpoint implementation file storeService and do not understand it because I have no typed constructor in any of the files, getters and setters I have the right and above any dependence is used to each other. Can someone please help me and explain what is happening? thank you very much
PD i have not put some code for readability issues and i easyly reach limit caracters, if someone needs to watch, let me know.
Ok, i allready solved my problem. Inside the endpoints.xml file a declared my ws with a id and i d already have declared the implementation ws file with a #Service annotation, so the exception is now clear to me...

Nested transaction on Spring

I found some strange behavior when using nested Spring transactions: when, in the same class, a method annotated as #Transactional calls another method also annotated as #Transactional the second annotation is not used.
Let's consider the following class:
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
final Main main = context.getBean(Main.class);
// First Op
System.out.println("Single insert: " + main.singleInsert());
// Second Op
main.batchInsert();
// Third Op
main.noTransBatchInsert();
}
#PersistenceContext
private EntityManager pm;
#Transactional(propagation=Propagation.REQUIRED)
public void batchInsert() {
System.out.println("batchInsert");
System.out.println("First insert: " + singleInsert());
System.out.println("Second insert: " + singleInsert());
}
public void noTransBatchInsert() {
System.out.println("noTransBatchInsert");
System.out.println("First insert: " + singleInsert());
System.out.println("Second insert: " + singleInsert());
}
#Transactional(propagation=Propagation.REQUIRES_NEW)
public int singleInsert() {
System.out.println("singleInsert");
Pojo p = new Pojo();
pm.persist(p);
return p.getId();
}
}
The entity if the following class:
#Entity
public class Pojo {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
private int id;
#Override
public String toString() {
return "Pojo: " + id;
}
public int getId() {
return id;
}
}
and the String parts applicationContext.xml:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd">
<tx:annotation-driven />
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="MyPersistenceUnit" />
</bean>
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
</beans>
and the configuration class (I could have merge this in applicationContext.xml).
#Configuration
#ImportResource("/META-INF/applicationContext.xml")
public class Config {
#Bean
public Main main() {
return new Main();
}
}
For completeness the persistence.xml file:
<persistence 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_2_0.xsd" version="2.0">
<persistence-unit name="MyPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.connection.driver_class" value="org.h2.Driver" />
<property name="hibernate.connection.url" value="jdbc:h2:mem:TestDSJPA2;DB_CLOSE_DELAY=-1;LOCK_MODE=0" />
<!--<property name="hibernate.connection.url" value="jdbc:h2:mem:TestDSJPA2;DB_CLOSE_DELAY=-1;LOCK_MODE=0" />-->
<property name="hibernate.connection.username" value="sa" />
<property name="hibernate.connection.password" value="" />
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.c3p0.min_size" value="5" />
<property name="hibernate.c3p0.max_size" value="20" />
<property name="hibernate.c3p0.timeout" value="300" />
<property name="hibernate.c3p0.max_statements" value="50" />
<property name="hibernate.c3p0.idle_test_period" value="3000" />
</properties>
</persistence-unit>
</persistence>
So in the main class, the first operation is performed as expected that is in a new transaction. The output (including some DEBUG messages) is:
DEBUG o.h.transaction.JDBCTransaction - begin
singleInsert
DEBUG o.h.transaction.JDBCTransaction - commit
Single insert: 1
The second operation gives the following output:
batchInsert
singleInsert
DEBUG o.h.transaction.JDBCTransaction - begin
First insert: 2
singleInsert
Second insert: 3
DEBUG
This is not what I expected since in annotating singleInsert with #Transactional(propagation=Propagation.REQUIRES_NEW) I would expect a new transaction to be created for every call which is not what's happening since the same top level transaction is used for both insertion.
The third operation fails as well as no transaction is created at all:
noTransBatchInsert
singleInsert
DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
First insert: 0
singleInsert
DEBUG o.h.e.def.AbstractSaveEventListener - delaying identity-insert due to no transaction in progress
Second insert: 0
In the #Configuration beans Spring ensures that calls to the method on the same class are proxified which is obviously not happening here. Is there a way do change this behavior?
This behavior is the documented behavior of Spring when using the proxy mode for AOP. It can be changed by switching to the aspectj mode which perform code instrumentation either on compilation or at runtime.
This is not specifically a problem with #Transactional. It is due to the configuration of your <tx:annotation-driven/>.
Spring uses two different AOP mechanisms: JDK dynamic proxies or CGLIB. JDK dynamic proxies is the default and it works through the use of interfaces at run-time. CGLIB works by generating subclasses at compile-time. If you specify <tx:annotation-driven proxy-target-class="true"/>, Spring will use CGLIB, and your second #Transactional will fire.
You can read more about the subject here.
The default advice mode for processing #Transactional annotations is
proxy, which allows for interception of calls through the proxy only.
Local calls within the same class cannot get intercepted that way. For
a more advanced mode of interception, consider switching to aspectj
mode in combination with compile-time or load-time weaving.
Taken from Spring reference. https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/data-access.html#tx-propagation-nested

Resources