How to specify rollback in Spring using wildcards? - java

I have following code in Spring -
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" rollback-for="org.springframework.dao.DataAccessException" no-rollback-for="java.lang.IndexOutOfBoundsException"
timeout="30" />
</tx:attributes>
</tx:advice>
This configuration will rollback for DataAccessException and all its sub-exceptions. i.e. the exception hierarchy is rolled back. However I want to be able to rollback a set of exceptions (not belonging to same hierarchy). Is it possible to write something like -
<tx:advice id="transactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" rollback-for="org.springframework.*" no-rollback-for="java.lang.*"
timeout="30" />
</tx:attributes>
</tx:advice>
I have tried the above code but it does not work.

No, you can't use wildcards, but
<tx:method name="*" propagation="REQUIRED" rollback-for="org.springframework" no-rollback-for="java.lang" />
will do that you want. Match is positive if the Exception class name contains the pattern.

Spring typically uses plain substring as exception matching pattern.
For example, RollbackRuleAttribute javadoc
NB: Consider carefully how specific the pattern is, and whether to
include package information (which is not mandatory). For example,
"Exception" will match nearly anything, and will probably hide other
rules. "java.lang.Exception" would be correct if "Exception" was meant
to define a rule for all checked exceptions. With more unusual
exception names such as "BaseBusinessException" there's no need to use
a fully package-qualified name.
so you can try to use "org.springframework.". However it doesn't seem that this is documented, Spring documentation only mentions that rollback-for has comma-delimeted format.
rollback-for Exception(s) that trigger rollback; comma-delimited. For example, com.foo.MyBusinessException,ServletException

Related

JPA find method persists data

I am using spring jpa. I have implemented transaction management using
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'find' are read-only -->
<tx:method name="find*" read-only="true" />
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*" rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="transactionalServiceOperation"
expression="execution(* com.test..*ServiceImpl.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="transactionalServiceOperation" />
</aop:config>
Recently i noticed that although in some cases transaction management is working but in other cases it is not. For example , i have this piece of code inside a service method which is annotated by #org.springframework.transaction.annotation.Transactional.
The code inside the method
guardianService.save(newFather);
parentsSet.add(newFather);
Guardian oldMother = guardianService.findById(motherId);
In the above case the data in the database does not persis till the 3rd line. As soon as the application finishes executing the 3rd line the data of newFather gets comited to the database even if the application generates Exception after the 3rd line.
Code snippet of guardianService.findById(motherId)
#Override
public Guardian findById(long guardianId) {
return guardianRepository.findByGuardianId(guardianId);
}
Inside GuardianRepository
public interface GuardianRepository extends JpaRepository<Guardian, Long> {
Guardian findByGuardianId(long id);
}
Code snippet of guardianService.save(newFather);
#Override
#Transactional
public Guardian save(Guardian guardian) {
return guardianRepository.save(guardian);
}
So my question is does the find() method somehow calls the flush() or commit()?
The find() method actually does invoke the flush method. By default in JPA, FlushModeType is set to AUTO, which means that if query to database occurs, the data in database has to be up to date for current transaction. From definition:
When queries are executed within a transaction, if FlushModeType.AUTO
is set on the Query object, or if the flush mode setting for the
persistence context is AUTO (the default) and a flush mode setting has
not been specified for the Query object, the persistence provider is
responsible for ensuring that all updates to the state of all entities
in the persistence context which could potentially affect the result
of the query are visible to the processing of the query.

Spring transaction management txAdvice

I've got some trouble while configuring spring transaction manager. The application I'm working on has a layered architecture. Therefore it has a service layer containing all the transactional services. I wanted for spring to rollback the transaction when a checked (application specific) exception has occurred. I succeeded doing that by annotation as follows:
#Transactional(value="transactionDds", rollbackfor="Throwable")
This works fine. But since I've so many services hence I want to move this configuration to XML (spring DAO context file). This is what I've done:
<tx:advice id="txAdvice" transaction-manager="transactionManagerDds">
<tx:attributes>
<tx:method name="*" read-only="false" propagation="REQUIRED" rollback-for="Throwable"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="transRollbackOp" expression="execution(*fr.def.iss.ult.moduleManagement.service.dds.*.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transRollbackOp"/>
</aop:config>
<bean id="transactionManagerDds" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="beanDataSourceFactory" />
<qualifier value="transactionDds"/>
</bean>
So basically, I'va a transaction manager which is associated to an advice which rolls back for the possible methods when a Throwable exception occurs. And this advice is linked to an AOP config that way we specify all the interfaces in the service layer of application on which this transaction configuration is to be applied. But this doesn't work. Transaction doesn't roll back Throwable exception occurs. I don't understand that this works with annotation but not with declarative configuration in XML.
I'm really looking forward for your suggestions. I'm totally blocked. Plz help me out. Thanx in advance.
<aop:config>
<aop:pointcut id="transRollbackOp" expression="execution(*fr.def.iss.ult.moduleManagement.service.dds.*.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transRollbackOp"/>
</aop:config>
In your <aop:config /> the expression you entered is invalid. It should at least contain a whitespace between * and fr.def.
Next instead of .*.*.* I suggest writing ..*.* which selects all classes in all subpackages regardless of depth.
In short change your expression to execution(* fr.def.iss.ult.moduleManagement.service.dds..*.*(..)) should make it work.

Transactions in Spring/hibernate

we are using Spring and hibernate in our project and i have noticed that we have defined <tx:annotation-driven /> in sprint context file and if i put #Transactionalannotation for method i am successfully able to interact with database but if i remove #Transactional annotation from method i am getting exception stating that "No Hibernate Session bound to thread, and configuration does not allow creation of non-transactional one here"
is there any way by which i can define all the select operation as non Transactional(i mean without #Transactional annotation) and update and insert as Transactional
Using #Transactional(readOnly=true) is usually the best thing for select-only operations. Using hibernate in auto-commit mode can be wasteful when multiple select statements are needed to complete an operation.
I am able to resolve this issue by using below code in context xml file.
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<!-- the transactional semantics... -->
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="allServiceMethods" expression="execution(* com.test.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="allServiceMethods"/>
</aop:config>
As by default read-only="false" for #Transactional annotation.
So we need to make it as read-only="true" for all read operation(Thanks Affe for pointer)
to set read-only="true" for all select select operation make sure that you start your method name from get and rest below code will code for us. you can change your below configuration as per your need.
<tx:method name="get*" read-only="true"/>
For more information you can refer to below link
Spring Docs

Spring AOP advice not applied to a concrete class if pointcut specified on interface and hierarchy deeper than one level

So I have class C implements interface B and interface B extends interface A.
My aop-config.xml:
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="aMethods" expression="execution(* com.mypackage.A.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="aMethods"/>
</aop:config>
Basically I want for all classes implementing interface A their methods to run in transactional context.
It doesn't seem to work when the pointcut expression is pointing to interface A but it does work if pointing to interface B.
Any thoughts on that?
You have a pointcut for an exact match for type A NOT for subtypes. To include subtypes add a + to the pointcut.
<aop:pointcut id="aMethods" expression="execution(* com.mypackage.A+.*(..))"/>
For more information the AspectJ reference guide. AspectJ in Action 2nd is also a book I can recommend.

Legacy Spring application - what does the pointcut value mean?

I have "inherited" an old legacy Spring application. Currently it is using Spring 2.5 (just upgraded it once), and am looking to further upgrade it to Spring 3.
I understand most of the application configuration. There is just one part that I am "not 100%" about. I can guess roughly what it might mean but I need to be absolutely sure hence posting this question:
Here is the configuration snippet (depends on an annotation driven transaction manager not shown here):
<aop:config>
<aop:advisor pointcut="execution(* *..ProductManager.*(..))"
advice-ref="txAdvice" />
</aop:config>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="save*" />
<tx:method name="*" read-only="false" />
</tx:attributes>
</tx:advice>
My specific two questions are:
What does "execution(* ..ProductManager.(..))" mean (I understand pointcut parlance)
In the attributes section of the advice we are saying apply transaction to all save* related methods, and for everything read-only is false. Can anyone explain why that setting makes sense? Is it additive and effectively saying, for all methods with transaction support (ie. just save* methods) I also want those methods to NOT be read-only transactions. Or is it applying something different (ie. some form of transaction support) to every method of inclusive transacion filter (defined in pointcut).
Thanks for any clarifications. Please, no general answers - I need a concrete explanation for this.
As tx:method has attribute read-only with default value as false, means transaction is read/write.
So in my opinion,
<tx:method name="save*" read-only="false" />
<tx:method name="*" />
is equivalent to
<tx:method name="*" />
execution(* *..ProductManager.*(..)) means that, "for all the methods in the ProductManager class"
tx:advice settings are not additive.
It says that for all methods beginning with save use the default transaction settings.
For the others, this setting means they are NOT read-only transactions.
For the common sense, one would expect
<tx:method name="save*" read-only="false" />
<tx:method name="*" />

Categories

Resources