I have this technical doubt...
If I have an interface
public interface test{
#Transactional
public void mymethod();
}
and then I have my implementation
public class testImpl implements test{
#Override
public void mymethod(){
//..do something
}
}
Since I am using #Override, will my annotation #Transactional, #Lock or any other persist on my implementation? or will overriden by the interface method without adding any special behaviour from the annotation?
Best answer I have read on this matter:
See this link https://stackoverflow.com/a/5551597/3447634
COPY OF THAT ANSWER:
"It really all depends on your application architecture, in my opinion. It depends on how you are proxying your classes. If you have your app set to "proxy-target-class='true'" (in your application context, then your #Transactional information wont be picked up if you annotate the Interface.
Check out The Spring Docs -- "Tips" for more information.
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad."
Related
I have method M with #Transactional in service A.
I have service B extends A with overrided method M.
Will be overrided method M still transactional?
Or I should add there #Transactional?
What you are actually asking : is the #Transactional annotation on the method inherited.
Short answer : no. Annotations on methods are never inherited.
Long answer : see this post.
Most of the time, you can get away with a single #Transactional at the class level. But sometimes you need to customize just one method to behave differently. In these cases it's still redundant to mark all other methods with identical #Transactional annotations.
Warp-persist provides a facility where you can override the class's transactional behavior with a specific #Transactional on a particular method if desired:
#Transactional
public class MyRepository {
public void save(Thing t) { .. }
#Transactional(rollbackOn = NoSuchEntityException.class) //optional
public void remove(Thing t) { .. }
public Thing fetch(Long id) { .. }
}
In the example above, save() and fetch() have standard transactional behavior as specified at the class-level. But remove() has a specific rollbackOn clause which is used instead.
Remember that private methods cannot be intercepted for transaction wrapping. This is because you cannot override private methods in subclasses. If any such methods are encountered, they will be silently ignored.
For Spring #Transactional using proxies (JDK or Cglib) with the default implementation, the method M will inherit the super class annotation attributes and will be transactional.
We can put the annotation on definitions of interfaces, classes, or directly on methods. They override each other according to the priority order; from lowest to highest we have: interface, superclass, class, interface method, superclass method, and class method.[1]
This behavior happens in the SpringTransactionAnnotationParser.[2]
All of the previous imply that the invocations are properly intercepted by Spring. Simply speaking, it needs to be a Spring bean, on a public method, and invoked from another class instance.[3]
[1]Transaction Propagation and Isolation in Spring #Transactional
[2]Spring framework source
[3]Transaction Management Spring documentation
Spring doc has the two recommendations:
Spring recommends that you only annotate concrete classes (and methods
of concrete classes) with the #Transactional annotation, as opposed to
annotating interfaces. You certainly can place the #Transactional
annotation on an interface (or an interface method), but this works
only as you would expect it to if you are using interface-based
proxies. The fact that Java annotations are not inherited from
interfaces means that if you are using class-based proxies
(proxy-target-class="true") or the weaving-based aspect
(mode="aspectj"), then the transaction settings are not recognized by
the proxying and weaving infrastructure, and the object will not be
wrapped in a transactional proxy, which would be decidedly bad.
(from http://static.springsource.org/spring/docs/3.0.x/reference/transaction.html)
and
Spring AOP uses either JDK dynamic proxies or CGLIB to create the
proxy for a given target object. (JDK dynamic proxies are preferred
whenever you have a choice).
(from http://static.springsource.org/spring/docs/3.0.x/reference/aop.html#aop-understanding-aop-proxies)
Do I understand correctly that in order to follow both recommendations, I need to have #Transactional annotation on concrete class, but still provide an interfaces (that this class implements) containing all transactional methods, so that Spring can use JDK dynamix proxies for this interface?
It works like this
Have a business interface with methods, do not annotate interface methods with #Transactional
Write an implementation class for interface defined above and annotate methods in impl class with #Transactional
As spring recommends usage of JDK dynamic proxies which are interface based hence we need to have business interface in place.
Also, as stated
Java annotations are not inherited from interfaces
We need to annotate concrete / implementation class methods with #Transactional
I'm mixing spring-data and CXF to create a RESTful endpoint that creates neo4j nodes. My structure is a set Interfaces which define the public facing methods, and my implementations which have several private methods under that are called by my public methods.
My private methods have spring-tx's #Transactional on them, and when I try to call these from my public methods, I get a org.neo4j.graphdb.NotInTransactionException. Below is a GitHub project that is setup to show my configuration and you can also run it to see what's wrong:
https://github.com/NicholasAStuart/broken-spring-neo4j-cxf.git
Can anyone help me? I've followed the steps from the documentation on spring-data-neo4j, but I cannot seem to get this working, can anyone help me?
The #Transactional annotation does not work on private methods.
From the Spring documentation:
When using proxies, you should apply the #Transactional annotation
only to methods with public visibility. If you do annotate protected,
private or package-visible methods with the #Transactional annotation,
no error is raised, but the annotated method does not exhibit the
configured transactional settings. Consider the use of AspectJ (see
below) if you need to annotate non-public methods.
You may be able to use the aspectj mode to enable this behavior on any type of method.
As highlighter on chapter 11.5.6 of spring manual:
Method visibility and #Transactional
When using proxies, you should apply the #Transactional annotation
only to methods with public visibility. If you do annotate protected,
private or package-visible methods with the #Transactional annotation,
no error is raised, but the annotated method does not exhibit the
configured transactional settings. Consider the use of AspectJ (see
below) if you need to annotate non-public methods.
The question from the title in code:
#Transactional (readonly = true)
public interface FooService {
void doSmth ();
}
public class FooServiceImpl implements FooService {
...
}
vs
public interface FooService {
void doSmth ();
}
#Transactional (readonly = true)
public class FooServiceImpl implements FooService {
...
}
From http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
The Spring team's recommendation is that you only annotate concrete classes with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this will only work as you would expect it to if you are using interface-based proxies. The fact that annotations are not inherited means that if you are using class-based proxies then the transaction settings will not be recognised by the class-based proxying infrastructure and the object will not be wrapped in a transactional proxy (which would be decidedly bad). So please do take the Spring team's advice and only annotate concrete classes (and the methods of concrete classes) with the #Transactional annotation.
Note: Since this mechanism is based on proxies, only 'external' method calls coming in through the proxy will be intercepted. This means that 'self-invocation', i.e. a method within the target object calling some other method of the target object, won't lead to an actual transaction at runtime even if the invoked method is marked with #Transactional!
(Emphasis added to the first sentence, other emphasis from the original.)
Spring's recommendation is that you annotate the concrete implementations instead of an interface. It's not incorrect to use the annotation on an interface, it's just possible to misuse that feature and inadvertently bypass your #Transaction declaration.
If you've marked something transactional in an interface and then refer to one of its implementing classes elsewhere in spring, it's not quite obvious that the object that spring creates will not respect the #Transactional annotation.
In practice it looks something like this:
public class MyClass implements MyInterface {
private int x;
public void doSomethingNonTx() {}
#Transactional
public void toSomethingTx() {}
}
You can put them on the interface but be warn that transactions may not end up happening in some cases. See the second tip in Secion 10.5.6 of the Spring docs:
Spring recommends that you only annotate concrete classes (and methods of concrete classes) with the #Transactional annotation, as opposed to annotating interfaces. You certainly can place the #Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you are using interface-based proxies. The fact that Java annotations are not inherited from interfaces means that if you are using class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), then the transaction settings are not recognized by the proxying and weaving infrastructure, and the object will not be wrapped in a transactional proxy, which would be decidedly bad.
I would recommend putting them on the implementation for this reason.
Also, to me, transactions seem like an implementation detail so they should be in the implementation class. Imagine having wrapper implementations for logging or test implementations (mocks) that don't need to be transactional.
Supporting #Transactional on the concrete classes:
I prefer to architect a solution in 3 sections generally: an API, an Implementation and a Web (if needed). I try my best to keep the API as light/simple/POJO as possible by minimizing dependencies. It's especially important if you play it in a distributed/integrated environment where you have to share the APIs a lot.
Putting #Transactional requires Spring libraries in the API section, which IMHO is not effective. So I prefer to add it in the Implementation where the transaction is running.
Putting it on the interface is fine as long all foreseeable implementers of your IFC care about TX data (transactions aren't problems that just databases deal with). If the method doesn't care about TX (but you need to put it there for Hibernate or whatever), put it on the impl.
Also, it might be a bit better to place #Transactional on the methods in the interface:
public interface FooService {
#Transactional(readOnly = true)
void doSmth();
}
I have a strange behaviour when autowiring
I have a similar code like this one, and it works
#Controller
public class Class1 {
#Autowired
private Class2 object2;
...
}
#Service
#Transactional
public class Class2{
...
}
The problem is that I need that the Class2 implements an interface so I've only changed the Class2 so it's now like:
#Controller
public class Class1 {
#Autowired
private Class2 object2;
...
}
#Service
#Transactional
public class Class2 implements IServiceReference<Class3, Long>{
...
}
public interface IServiceReference<T, PK extends Serializable> {
public T reference(PK id);
}
with this code I get a org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type for Class2.
It seems that #Transitional annotation is not compatible with the interface because if I remove the #Transitional annotation or the implements IServiceReference<Class3, Long> the problem disapears and the bean is injected (though I need to have both in this class). It also happens if I put the annotation #Transitional in the methods instead of in the Class.
I use Spring 3.0.2 if this helps.
Is not compatible the interface with the transactional method?
May it be a Spring bug?
The problem is that your Class1 needs a reference to IServiceReference and not the concrete reference of Class2
#Controller
public class Class1 {
#Autowired
private IServiceReference object2;
...
}
The reason this is that Spring is creating a dynamic proxy for classes that you marked #Transactional. Thus when Class2 is created its wrapped in a Proxy object that is obviously not of type Class2 but is of type IServiceReference.
If you want the behavior of using Class2 with proxy support you will have to turn on CGLIB
Read below:
From Springs Doc:
Spring AOP defaults to using standard
J2SE dynamic proxies for AOP proxies.
This enables any interface (or set of
interfaces) to be proxied.
Spring AOP can also use CGLIB proxies.
This is necessary to proxy classes,
rather than interfaces. CGLIB is used
by default if a business object does
not implement an interface. As it is
good practice to program to interfaces
rather than classes, business classes
normally will implement one or more
business interfaces. It is possible to
force the use of CGLIB, in those
(hopefully rare) cases where you need
to advise a method that is not
declared on an interface, or where you
need to pass a proxied object to a
method as a concrete type.
It is important to grasp the fact that
Spring AOP is proxy-based. See the
section entitled Section 6.6.1,
“Understanding AOP proxies” for a
thorough examination of exactly what
this implementation detail actually
means.
The Transactional annotation instructs Spring to generate proxy objects around the annotated beans, to implement the transactional semantics. The generated proxy will implement the same interfaces as the target bean. So if your target bean implements IServiceReference, then so will the generated proxy.
If the target bean has no implemented interfaces, then the generated proxy will instead be a subclass of the target bean type.
In your original example, the transactional proxy will be a subclass of Class2, because Class2 implemented no interfaces. When you changed Class2 to implement IServiceReference, the generated proxy no longer extended Class2, and instead implemented IServiceReference. This caused your ClassCastException.
The best approach to this situation is to remove the reference from Class1 to Class2, and instead talk to Class2 purely through its interfaces. Class2 can implement as many interfaces as you like, the proxy will implement all of them.
You can force Spring to generate subclass proxies regardless of the interfaces, but it's additional complexity, and I'd recommend against it.
You can force it to proxy by adding
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)
also see this documentation.