Clarification Request about Declarative Transaction via XML configuration in Spring Framework - java

I am studying Spring Declarative Transaction via XML configuration reading this article:
http://www.tutorialspoint.com/spring/declarative_management.htm
I am only having some proble to understand well how AOP work in this case, in my Beans.xml configuration file I have:
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="create"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="createOperation"
expression="execution(* com.tutorialspoint.StudentJDBCTemplate.create(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="createOperation"/>
</aop:config>
So, what exactly means this configuration?
I think that work in the following way (but I am not sure):
The transaction semantics to apply are encapsulated in the definition and I think that, in this case, simply specify that the create() method definied in the StudentDAO interface have to be a transactional behavior (is it right?)
Regarding the meaning of the content of aop:config tag I think that only ensure that the above transactional advice runs for any execution of com.tutorialspoint.StudentJDBCTemplate.create() method
Is it right? Or am I missing something?
Tnx
Andrea

You are right,
aop:pointcut will find out all the joinpoints where advise should be applied, defined with tx:advice.
also tx:advice gives extra tags to filter out these join points using tx:method tags with method attribute.
In above mentioned example,
pointcut will find only one joinpoint, and tx:advice will filter out joinpoints with tx:method's name attribute and apply specified configuration.In example default configuration values will be used.

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.

How exactly work Spring AOP named pointcuts? For what are used?

I am studying for the Spring Core certification and I have the following doubt related to AOP named pointcut
So for example I can have the following code into an XML configuration file that defines pointut with no name:
<aop:config>
<aop:aspect ref=“propertyChangeTracker”>
<aop:before pointcut=“execution(void set*(*))” method=“trackChange”/>
</aop:aspect>
</aop:config>
<bean id=“propertyChangeTracker” class=“example.PropertyChangeTracker” />
And this should work in the following way:
First it defines the pointcut as all the method having name that begin with set and that take a single parameter (of any type) returning void.
And it is definied the advice as the trackChange() method inside the class example.PropertyChangeTracker
So what it happens is that when a setter method is called during the application lifecycle it is automatically called the trackChange() method inside the class example.PropertyChangeTracker.
Ok, this is pretty simple.
Now instead I have this AOP XML configuration that contains named pointcuts:
<aop:config>
<aop:pointcut id=“setterMethods” expression=“execution(void set*(*))”/>
<aop:aspect ref=“propertyChangeTracker”>
<aop:after-returning pointcut-ref=“setterMethods” method=“trackChange”/>
<aop:after-throwing pointcut-ref=“setterMethods” method=“logFailure”/>
</aop:aspect>
</aop:config>
<bean id=“propertyChangeTracker” class=“example.PropertyChangeTracker” />
As in the first configuration the pointcut remain related to some particulars setter methods (but in this case the advices are respectivelly after-returning and after-throwing.
And the definied advices are the trackChange() and the logFailure() methods definied inside the example.PropertyChangeTracker class.
Differently from the first example the 2 advices are definied a name that is represented by the value of the pointcut-ref=“setterMethods”. But what exatly means? What can be used for?
Tnx
Long question, simple answer: You can refer to the pointcut by its name, so if you have multiple advices referring to the same pointcut you only need to change it in one place and leave the references untouched. This is similar to using a variable vs. literals in Java code.
Look at your own example: The two advices trackChange and logFailure both use the same pointcut, which is quite convenient. DRY - don't repeat yourself. ;-) Sometimes pointcuts are a bit more complex than yours, they can span multiple lines in complex scenarios.

Global configuration in Spring annotational transactions?

We use Spring transactions using annotational #Transactional attribute instead of XML alternative. Is it possible to specify some service methods as "read-only" as declared in XML version?
As far as I know, in XML version, you can specify methods and read-only configurations as:
<tx:attributes>
<!-- all methods starting with 'get' are read-only -->
<tx:method name="get*" read-only="true"/>
<tx:method name="find*" read-only="true"/>
<!-- other methods use the default transaction settings (see below) -->
<tx:method name="*"/>
</tx:attributes>
But I want to use this configurations in annotational services. Is that possible?
I don't think you can translate that xml to #Transactional. That annotation is to be placed on methods and/or classes and the usage is different.
You need to think differently: for example, if you have a class with many get* methods then you place a #Transactional(readOnly=true) at class level and then for each method you don't want to be readOnly you place another #Transactional(readOnly=false). Also, you can place #Transactional on interfaces and if you can create interfaces common for many classes you can define the transactional behavior in one place: in the interface.

How to instantiate spring bean without being referenced from aop:aspect

Using Spring and Java;
I have a pointcut which works OK. Now I want to remove the pointcut and AOP from the spring and just trigger the event with an event from inside the java code but I want "myAdvice" bean still called via Spring and its properties set.
I want to get ridoff all advice things even in java code, no more advice or any trace of AOP, I already have a nice event system working. I just want to instantiate my bean via Spring.
When I remove the second code block (one starting with "aop:config") then I noticed the bean "myAdvice" is not called and instantiated anymore. How can i stil call it set its properties without referencing it from the "aop:aspect" ?
in my application context ;
<bean id="myAdvice" class="com.myclass">
<property name="name1" ref="ref1" />
<property name="name2" ref="ref2" />
</bean>
<aop:config proxy-target-class="true">
<aop:aspect id="myAspect" ref="myAdvice">
<aop:pointcut id="myPointcut" expression="execution(* com.myexcmethod" />
<aop:around pointcut-ref="myPointcut" method="invoke" />
</aop:aspect>
</aop:config>
Your configuration looks fine . Your bean should be instantiated as a singleton bean when the ApplicationContext loads up . Maybe you would want to check if you have a default-lazy-init setting which prevents eager loading of the beans.
If you want to be able to get at the bean itself, you can pass it into this function:
public static Object unwrapProxy(Object proxiedBean) throws Exception {
while(proxiedBean instanceof Advised) {
proxiedBean = ((Advised) proxiedBean).getTargetSource().getTarget();
}
return proxiedBean;
}
Note that you need to have the loop in order to ensure that you unwrap all the AOP advice.

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.

Categories

Resources