Spring Transaction Management: using #Transactional vs using AOP (<aop:advisor) - java

I have a confusion about Spring transaction management. In my application I implemented transaction management using #Transactional in the service class. And I configured my spring.xml is like:
<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="configLocation" value="classpath:hibernate.cfg.xml"/>
<beans:property name="hibernateProperties">
<beans:props>
<beans:prop key="hibernate.dialect">${jdbc.dialect}</beans:prop>
<beans:prop key="hibernate.show_sql">false</beans:prop>
<beans:prop key="hibernate.hbm2ddl.auto">update</beans:prop>
</beans:props>
</beans:property>
</beans:bean>
<!-- Transaction manager -->
<beans:bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<beans:property name="sessionFactory" ref="sessionFactory" />
</beans:bean>
If I implement transaction management in the configuration file like below without using #Transactional in the service class:
<aop:pointcut id="defaultServiceOperation"
expression="execution(* x.y.service.*Service.*(..))"/>
<aop:pointcut id="noTxServiceOperation"
expression="execution(* x.y.service.ddl.DefaultDdlManager.*(..))"/>
<aop:advisor pointcut-ref="defaultServiceOperation" advice-ref="defaultTxAdvice"/>
<aop:advisor pointcut-ref="noTxServiceOperation" advice-ref="noTxAdvice"/>
</aop:config>
does it give me any benefits over #Transactional? Someone told me using #Transactional is also implementation of AOP in spring. Can anyone explain me how?

It won't.
Benefits
If you don't need some very specified requirements or you have no performance issues, you shouldn't reinvent the wheel. Spring is almost perfectly designed, tested and sharped instrument, which can be replacement even for enterprise application servers. #Transactional is declarative way for managing transactions, it's far more convenient and readable than any aop xml configs. It's benefits include automatic handling of all transaction management aspects in declarative way: isolation and propagation levels (it's not easy to control nested transactions), timeouts, rollback conditions and distinct TransactionManagers for every single method of your service's class. Easy to read, easy to configure, easy to use.
#Transactional(readOnly = false, rollbackFor = ServiceException.class, isolation = Isolation.READ_COMMITTED)
public void myServiceJob(...)
When you see this method, it's easy to understand it's transactional attributes (without providing transactions implementation details in method). In case of plain AOP every time you want to know what happens in this method, you should check your xml config and find corresponding method, which is way less elegant.
On other hand, it's very hard to debug or use these proxies for any other declarative management. E.g. it's tricky (but not impossible) extract your bean from context and get something out of your wrapped bean using reflection (let's say, for monitoring purposes). In addition, when bean calls one of its method, it won't be delegated to proxy, because your bean knows nothing about proxy, so this refers to bean itself. The only way to cure this it to provide "self" field and set it in custom bean postprocessor (but your implementation suffers from this either).
Implementation
If Spring is configured to use transactional management, it's looking for #Transactional annotation on bean's definitions and creates auto-generated AOP proxy, which is subclass of your bean. Default behavior of Spring proxy is just delegating method's calls to underlying bean. Then Spring injects TransactionInterceptor with necessary TransactionManagers.
Code of interceptor looks quite simple:
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {#code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
#Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
Inside of invokeWithinTransaction TransactionInterceptor determines whether should invocation be in scope of caller transaction (if one exists) or in a new one (it's about propagation level). Then it choses corresponding TransactionManager, configures timeout and isolation level, then invokes the method. After it decides if transaction should be commited or rolled back (choice is made based on caught exception and timing).

Related

AOP advice on methods other than execute method of spring batch tasklet not being applied

This issue has started after migrating from spring 4.1.2 to 5.0.5, spring batch to 3.0.9 to 4.0.1 and hibernate 4.2.0 to 5.2.16
I have a spring batch tasklet of the format -
public class MyTasklet implements Tasklet {
public RepeatStatus execute(StepContribution arg0, ChunkContext arg1) {
a();
}
public void a(){
//a few hibernate calls here
}
}
Now I want my hibernate transaction boundary to be the method a() [being called from execute] and not the execute() method.
But when I try applying point-cuts to achieve the same I get a message "no transaction in progress". I have provided the sample xml below.
In the aop pointcut -instead of the method name 'a'[i.e public * myPackage.MyTasklet.a(..)], if I use * (i.e public * myPackage.MyTasklet.*(..)] or 'execute'[i.e public * myPackage.MyTasklet.execute(..)] the code works fine. Due to some technical reasons it is important to have the boundary at 'a' due to which I cannot have 'execute' or any other method as the boundary.
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" />
</tx:attributes>
</tx:advice>
<bean id="transactionManager"
class="org.springframework.orm.hibernate5.HibernateTransactionManager">
<property name="sessionFactory" ref="mySessionFactory" />
</bean>
<aop:config>
<aop:pointcut id="Op1"
expression="execution(public * myPackage.MyTasklet.a(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="Op1" />
</aop:config>
This question has been asked hundreds of times here. Your method a() is called internally, but internal method calls are never intercepted by Spring AOP because in that case you actually call this.a(). This does not go through the wrapping dynamic proxy used by Spring AOP. If a() was called from outside, e.e. by another component, it would work. This behaviour is comprehensively documented in the Spring AOP manual.
If you want to intercept internal method calls you have to use AspectJ instead of Spring AOP. How to configure Spring for AspectJ and LTW (load-time weaving) is also documented in the Spring manual.
P.S.: This is completely unrelated to your version upgrades. In older Spring and Spring Batch versions it would be the same. You mixed refactoring (version upgrade) with functional changes, which you should never do. Too many moving targets for debugging. Refactoring means to change the code (or the configuration, in this case) without changing its functionality.

spring #Transactional is not rolling back

I have a similar piece of code inside a #Service:
#Autowired
private MyDAO myDAO;
#Transactional
#Override
public void m(...) {
Integer i = null; // this is just to simulate a NPE
myDAO.saveX(...);
i.toString(); // throws NullPointerException
myDAO.saveY(...);
}
This piece of code throws a NPE which is not catched by Spring and so my code is not rolled back. Any idea why is this happening?
I have the same configuration as in other places in my app and in those places it works as expected.
<jee:jndi-lookup id="dataSource" jndi-name="jdbc/MyDataSource"/>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
Possible reasons:
Your bean is not managed by Spring, a.k.a created with new instead of taken from the application context.
you're calling the m() method in another method of the same class/bean. By default Spring uses proxies to manage declarative transactions and internal calls are not supported.
you're throwing checked exception and not using #Repository on the dao. Declarative transactions work only for runtime exceptions. #Reposiotry "fixes" that by wrapping all exceptions in a DataAccessException. (probably not the case since NPE is runtime)
Try adding rollbackFor parameter to #Transactional annotation
#Transactional(rollbackFor=NullPointerException.class)
I found the solution here. I have multiple contexts and some of them didn't have <tx:annotation-driven />.

ProxyFactoryBean in Spring

Can someone explain ProxyFactoryBean in simple terms?
I see this being quoted lot of places.
ProxyFactoryBean is used to apply interceptor logic to an existing target bean, so that when methods on that bean are invoked, the interceptors are executed before-and-after that method call. This is an example of Aspect Oriented Programming (AOP).
This is best explained using a simple example. A classic use-case for AOP is to apply caching to the result of a method call. This could be wired up using ProxyFactoryBean as follows:
<bean id="targetService" class="com.x.MyClass"/>
<bean id="cachingInterceptor" class="com.x.MyCachingInterceptor"/>
<bean id="cachedService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="targetService"/>
<property name="interfaces">
<list>
<value>com.x.MyService</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>cachingInterceptor</value>
</list>
</property>
</bean>
We have a bean targetService of type com.x.MyClass, which implements the interface com.x.MyService. We also have a interceptor bean called cachingInterceptor, which implements the interface org.aopalliance.intercept.MethodInterceptor.
This config will generate a new bean, called cachedService, which implements the MyService interface. Any calls to the methods on that object will first be passed through the cachingInterceptor object's invoke() method, which in this case would look for the results of previous method calls in its internal cache. It would either return the cached result, or allow the method call to proceed to the appropropriate method on targetService.
targetService itself knows nothing of this, it's completely unaware of all this AOP stuff going on.
ProxyFactoryBean is heavily used internally within Spring to generate proxies for a variety of reasons (e.g. remoting stubs, transaction management), but it's perfectly suitable for use in application logic also.
The ProxyFactoryBean applies aspects to an existing bean. You start out with your existing bean (the target bean), which spring "wraps" to add the aspects you provide. The returned bean has the same interface as your original bean, but with the additional aspects weaved around the target bean's methods.

Lazy-loading with Spring HibernateDaoSupport?

Greetings I am developing a non-webapplication using Spring+Hibernate.
My question is how the HibernateDaoSupport handles lazy-loading , because after a call do DAO , the Session is closed.
Take a look at following psuedo-code:
DAO is like:
CommonDao extends HibernateDaoSupport{
Family getFamilyById(String id);
SubFamily getSubFamily(String familyid,String subfamilyid);
}
Domain model is like:
Family{
private List<SubFamily> subfamiles;
public List<SubFamily> getSubFamiles();
}
SubFamily{
private Family family;
public Family getFamily();
}
In the application I get DAO from app-context and want to following operations.Is this possible to do with lazy-loading because AFAIK after every method (getFamilyById() , getSubFamily() ) the session is closed.
CommonDAO dao=//get bean from application context;
Family famA=dao.getFamilyById(familyid);
//
//Do some stuff
List<SubFamily> childrenA=fam.getSubFamiles();
SubFamily asubfamily=dao.getSubFamily(id,subfamilyid);
//
//Do some other stuff
Family famB=asubfamily.getFamily();
My question is how the HibernateDaoSupport handles lazy-loading , because after a call to DAO, the Session is closed.
The DAOs don't create/close a Session for each call, they are not responsible for this and this is usually done using the "Open Session in View" pattern (Spring provide a filter or an interceptor for this). But this is for web apps.
In a swing app, one solution is to use long session. You'll have to decide well-defined points at which to close the session to release memory. For small applications, this is usually straightforward and will work. For bigger (i.e. real life apps), the right solution is to use one session per frame/internal frame/dialog. It's harder to manage but will scale.
Some threads you might want to read:
hibernate LazyInitializationException in rich client app
Spring/Hibernate long session support or best practice?
Keep hibernate session open in swing client? (this one is IMHO the most interesting, especially #9)
And the Hibernate and Swing demo app
If you are already using Spring you can make use of its Transaction-Declaration. Using this you are able to declare a transaction for a specific method. This keeps the Sessio open for the complete tx.
Declare the Transaction Pointcut
<!-- this is the service object that we want to make transactional -->
<bean id="SomeService" class="x.y.service.SomeService"/>
<tx:advice id="txAdvice" transaction-manager="txManager">
<!-- 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>
<!-- ensure that the above transactional advice runs for any execution
of an operation defined by the FooService interface -->
<aop:config>
<aop:pointcut id="MyServicePointcut" expression="execution(* x.y.service.SomeService.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="SomeServiceOperation"/>
</aop:config>
<bean id="txManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
Now you can do this lazy keeping the Session open for the complete Method.
public class SomeService()
{
public Family getFamily()
{
Family famA=dao.getFamilyById(familyid);
//Do some stuff
List<SubFamily> childrenA=fam.getSubFamiles();
SubFamily asubfamily=dao.getSubFamily(id,subfamilyid);
//Do some other stuff
return asubfamily.getFamily();
}
}
See Chapter 9 of Springs Tx Reference for further details.

Switching authentication approaches at runtime with Spring Security?

Typically, when you declare different "<authentication-provider>" for your application (webapp in my case), Spring Security takes care of invoking providers one after another, incase of failure. So, say I have DatabaseAuthenticationProvider and LDAPAuthenticationProvider with DatabaseAuthenticationProvider declared first in the config file, at runtime, DatabaseAuthenticationProvider is invoked first and if authentication fails, LDAPAuthentication is tried. This is cool - However, what I need is a runtime switch.
I would like to have an option of chosing between these two approaches (database based authentication / ldap based authentication) and somehow swith the implementation based on thsi global setting.
How do I do it? Is it even possible with Spring-Security?
I will leave how to inject your own custom authentication provider to the other myriad of examples from Googleland and here on StackOverflow. It looks like it has to do with marking a particular bean with the xml. But hopefully I can fill in some of the other details for you.
So you've defined the class somewhat like above and I'll add more of the details that you'll need for Spring (i.e. merge the stuff from above as well.
public class SwitchingAuthenticationProvider implements AuthenticationProvider
{
....
public List<AuthenticationProvider> getProviders() { return delegateList; }
public void setProviders(List<AuthenticationProvider> providers) {
this.delegateList = providers;
}
....
}
This will allow you to inject a host of providers using spring:
<bean id="customAuthProvider1" class=".....CustomProvider1"> ... </bean>
<bean id="customAuthProvider2" class=".....CustomProvider2"> ... </bean>
...
<bean id="customAuthProviderX" class=".....CustomProviderX"> ... </bean>
<bean id="authenticationProvider" class="....SwitchingAuthenticationProvider">
<security:custom-authentication-provider/>
<!-- using property injection (get/setProviders) in the bean class -->
<property name="providers">
<list>
<ref local="customAuthProvider1"/> <!-- Ref of 1st authenticator -->
<ref local="customAuthProvider2"/> <!-- Ref of 2nd authenticator -->
...
<ref local="customAuthProviderX"/> <!-- and so on for more -->
</list>
</property>
</bean>
In the end how you populate the providers could be any means of getting the delegator a collection of providers. How they map up to which one to use is up to you. The collection could be a named mapped, based on the current state of the delegator. It could be a list of more than one to try. It could be two properties, "get/setPrimary" and "get/setSecondary" for fail-over like functionality. Once you have the delegator injected the possibilities are up to you.
Let me know if this isn't answering your question.
How about writing a delegating AuthenticationProvider that knows how to access your runtime switch and the actual instances of Database/LDAP AuthenticationProvider.
I'm thinking of something like:
public class SwitchingAuthenticationProvider implements AuthenticationProvider
{
private List<AuthenticationProvider> delegateList;
private int selectedProvider;
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException
{
AuthenticationProvider delegateTo = delegateList.get(selectedProvider);
return delegateTo.authenticate(authentication);
}
....
}

Categories

Resources