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 {
...
}
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:
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.
From http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
(Emphasis added to the first sentence, other emphasis from the original.)
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.
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:
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:Please take a look at the link below which illustrates the problem with a simple but explaining example:
http://kim.saabye-pedersen.org/2013/05/spring-annotation-on-interface-or-class.html