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
Related
The method getById is located in an Abstract class named AbstractCachedResult.
public abstract class AbstractCachedResult<T extends BaseResource> {
#Cacheable(value = "dynamicName")
public T getById(String id){
//program logic
}
}
Many other service classes will be inheriting from this class. For ex :
public class UserService extends AbstractCachedResult<User> {
//program logic
}
Since I am setting the #Cacheable(value = "dynamicName") in the abstract class I wouldn't be able to know the type of the class that was returned by the method. I need to be able to get the name of the class dynamically so that for each method invocation from its inherited class the correct cache is used.
I have came across another post. Here they are passing the entity class name as a parameter which I cannot do. I need to get the type of the returned data dynamically so that I could us the #Caching annotation which is the #2 soluton. Is there a way to do this?
Arguably, the simplest and most obvious solution, especially for maintainers, would be to override the getById(:String) method in the subclass, like so:
public class UserService extends AbstractCachedResult<User> {
#Cacheable("UserCache")
public User getById(String id) {
super.id(id);
}
// additional logic
}
Alternatively, you might be able to implement a "custom" CacheResolver (see doc and Javadoc) that is able to inspect the class generic signature of the (target) subclass.
Finally, under-the-hood, Spring's Cache Abstraction is implemented with Spring AOP. For real, low-level control, it should be possible to write custom AOP Interceptor not unlike Spring's default CacheInterceptor (Javadoc). Your own AOP Advice could even be ordered relative to the Cacheable Advice, if needed.
Honestly, I think the first option I presented above is the best approach. Not every service class may need to cache the result of the getById(:String) operation. Caching really depends on the transactional nature of the data and how frequently the data changes.
Use your best judgement.
I have an Ingestion class that exposes a single method ingest. This method processes each section of a passed in form (section 1, section 2, etc, etc).
I have private methods for each section, saving the entity as it processes through. I'm aware that #Transactional has no effect on private methods, however I do not want to expose these methods but would like to use the functionality that #Transactional provides.
I'm looking to make sure each section completes in its own Transaction; I could do this through 'AspectJ' (as other SO answers have suggested) instead of Spring's out the box implementation, but I am trying to avoid due to the system wide changes it would cause.
Any thoughts on another approach?
The pseudo code provided below gives a general idea on the structure of the class:
public Class Ingestion {
// Autowired Repo's
...
...
#Transactional
public void ingest(Form form){
this.processSection1(form);
this.processSection2(form);
this.processSection3(form);
}
#Transactional
private void processSection1(Form form){
// do specific section 1 logic
section1Repo.save(form);
}
#Transactional
private void processSection2(Form form){
// do specific section2 logic
section2Repo.save(form);
}
#Transactional
private void processSection3(Form form){
// do specific section3 logic
section3Repo.save(form);
}
}
=========================================================================
This is not a duplicate question as marked in the comments. I know #Transactional doesnt work on private methods. My question is more along the lines of 'how do we get around this Spring AOP issue without having to use AspectJ'
The reason this doesn't work is that annotations like #Transactional add additional functionality that is intercepted by Spring's proxy object that wraps the actual object. But when you call a private method on an object with the this keyword, you're going straight to the real object and bypassing the proxy.
One way to solve this is to #Autowire the object into itself, and make the transactional calls via that autowired variable. You can still access private methods that way, and the call will be to a Spring-managed proxy instead of the bare object.
You may extract these three processing methods in another class, make them public, but set the class constructor access level to package-local (but not private, since Spring can't proxy classes with private constructors), so no classes from other packages could access these methods just because they are not able to instantiate their class. It doesn't hide these methods completely, but may fit your needs. This trick can be done with an inner class as well (note that it must be declared with package-local access).
To completely hide these methods, you may make use of declarative transaction management by injecting TransactionTemplate bean and using its execute method in private methods. This feature comes out-of-the-box. See more here.
Also, take note that for creating new transaction on executing method B from method A, method B must be declared #Transactional with propagation type REQUIRES_NEW. Otherwise, any nested methods will be invoked in the same transaction started by initial calling method.
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."
Consider this #PointCut which gets triggered if a method is annotated with an #Secure annotation:
#Pointcut("execution(#Secure * *(..)) && #annotation(secure)")
public void accessOperation(final Access access) { }
This works perfectly well for methods like:
class Foo {
#Secure
public void secureMethod() { }
}
But is it possible to have a Pointcut which also gets triggered when the annotation only exists in a superclass/interface like this?
interface Foo {
#Secure
public void secureMethod();
}
class SubFoo implements Foo {
#Override
public void secureMethod() { // <--- execution of this method should be caught
/* .... */
}
}
EDIT:
This seems to be very closely related to: #AspectJ pointcut for subclasses of a class with an annotation
The only difference is that they use a class-level annotation, whereas I need a method-level annotation.
I don't know how AspectJ deals with annotations in such a scenario, but if he only checks the implementing class for a certain annotation, and that annotation is only found on the interface that the class implements, Java will report that infact that annoation is not present on the class method. You should annotate your annotation with #Inherited:
http://download.oracle.com/javase/6/docs/api/java/lang/annotation/Inherited.html
maybe this will do the trick (though in this case you should make sure that your Advice is not called multiple times).
I don't actually know the classes in my aspect
Considering what you are saying and the fact that #Inherited cannot be used on anything else but classes, you are implicitly hoping that AspectJ will do the job of finding out whether a method (or its overriden implementations and declarations) is annotated. This is much more than what is announced by AspectJ.
If your final objective is to secure some code, then all methods which should be secured should be properly annotated in the first place. So, the answer to your question is no, this is not possible in this context, especially if you know nothing about the classes.
However, there might be a workaround if you have access to an annotation processor. In this case, you could pick all #Secure annotation and work your way through the code with reflection to generate AspectJ code at compile time that would captures all method instances properly. Not easy, but possible.
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();
}