My colleague Rich Evans noticed this one. He noticed that our Spring transactional annotations were being ignored if the code invoking the proxy was groovy. Assume we have the following:
public interface MyService { boolean isThisWithinATransaction(); } public final class DefaultMyService implements MyService { @Transactional public boolean isThisWithinATransaction(); return TransactionAspectSupport.currentTransactionInfo().hasTransaction() } }If we dependency inject that service into a groovy class (using groovy 1.6.2) then the method returns false, if it dependency inject it into a Java class, then it returns true.
Note: the actual bug is not specific to Spring's Transactional annotations - it is broader than that - Spring AOP proxies just don't work as expected in groovy 1.6.2. Given how much Spring uses proxies, this is pretty painful!
I am not entirely sure what is involved in this issue - something to do with the fact that the method that the Spring proxy invokes doesn't have the Spring Transaction annotation on it, as it is actually one of Groovy's dispatching methods that gets called. The transactional interceptor is still in the call chain, as the decision to whether the method *could* be transactional is done from static analysis, the problem only exhibits itself during runtime.
I keep meaning to blog about my lessons learnt regarding testing strategies. One of those lessons is the further away your code is from the production environment, the less valuable those tests are. We were hit by this. All our production code (Controllers and services etc.) are written in groovy, but our tests are written using Java. This meant our integration tests passed but our production code failed.
Nothing beats those system level, black box tests. We use selenium for this, but just haven't got there yet.
No comments:
Post a Comment