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.
Related
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.
In our project we're trying to move from Spring standard AOP to AspectJ as explained in many places like this (we need to make transactional some private and protected methods).
We had been able to make this work fine with standard Spring annotations like #Transactional. But we face the problem that in our project there are some custom Annotations (not custom aspects) that are not recognized by AspectJ. For example, we have this annotation that 'extends' #Transactional (only modifies rollbackFor property):
#Target({ ElementType.METHOD, ElementType.TYPE })
#Retention(RetentionPolicy.CLASS)
#Transactional(rollbackFor = Exception.class)
public #interface TransactionalWithCheckedException {
}
Any idea on how to tell AspectJ to weaver also this custom annotations? Is it possible? If not, should i build custom Aspects extending Spring ones (i.e.: for #Transactional).
For more information this is the aop.xml:
<aspectj>
<aspects>
<!-- Aparently no need to explicit declare aspects like the ones used by Spring #Transactional or #Async, they work fine. -->
</aspects>
<weaver options="-XnoInline -Xreweavable -showWeaveInfo">
<include within="com.mycompany.myproject..*" />
</weaver>
And part of Spring's context config file:
<tx:annotation-driven mode="aspectj" />
<context:load-time-weaver />
Well, first of all, the Spring #Transactional annotation is not a meta-annotation, so it cannot be used on annotation types. Additionally, nothing in the spring transaction code would support this kind of usage. In order to support this kind of usage, you'll have to create a specialized aspect with the proper pointcuts to identify the join points at transaction boundaries, probably supporting both the original Spring #Transactional annotation and your custom annotation as well. You'll also need to provide the aspect with an implementation of TransactionAttributeSource to support you own source of metadata, in your case an implementation of that interface handling #TransactionalWithCheckedException annotation (your point of interest will be the TransactionAttribute.rollbackOn(Throwable ex) method). You can then use CompositeTransactionAttributeSource as the implementation of the TransactionAttributeSource so you can combine the metadata sources supporting Spring's #Transactional annotation and your annotation as well.
To sum it up, you'll need these two things to handle special transaction attributes:
a concrete Aspect supporting both your and Spring's annotations (probably a subclass of AbstractTransactionAspect, see AnnotationTransactionAspect for implementation ideas`
a TransactionAttributeSource implementation handling your transaction annotation. Use CompositeTransactionAttributeSource to combine support for your metadata with spring's metadata (AnnotationTransactionAttributeSource).
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.
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.
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.