views:

822

answers:

3

A while back I wrote an application which used Spring AOP for defining which methods were transactional. I am now having second thoughts as to how much of a great idea this was; I have been hit a few times after a minor refactor (changing method signatures etc), which of course doesn't become apparent until something actually goes wrong (and I have a logically inconsistent database).

So I'm interested in a few things:

  1. Have other people decided to revert to explicit transaction management (e.g. via @Transactional annotations)?
  2. Are there useful tools I can use as part of a build process to help identify whether anything has been "broken"?
  3. If people are using AOP to manage transactions, what steps are they taking to avoid the mistakes I've made?

I'm using IntelliJ IDEA which allows you to browse decorated methods and will refactor Spring XML config together with method name changes, but this is not always sufficient (adding a parameter to a method in the wrong place can affect whether an aspect fires for example)

+3  A: 

I am currently using declarative transaction management in the two Java projects I work on, specifying which methods need transactional scope with @Transactional annotation. In my opinion, it is a good mix of flexibility and robustness: you are able to see which methods have transactional behavior via a simple text search, can adjust isolation and propagation attributes by hand if needed, and the additional amount of typing is practically negligent.

On one of those projects, I have security/logging implemented via aspects and have occasionally stumbled on same obstacles you when renaming a method or changing signatures. In the worst case, I lost some logging data of user accessing contracts, and in one release, some user roles were not able to access all application features. Nothing major, but, as far as database transactions go, though, I think it's simply not worth it, and I it is better to type @Transactional bit yourself. Spring does the hard part, anyway.

javashlook
+1 - it's good advice to leverage the annotations in Spring 2.5.
duffymo
The reason I didn't originally do this is that it's ususally the business logic that has to be transactional as opposed to the individual persistence calls. I didn't want Spring imports all over the place - I wanted the persistence implementation details to be isolated as much as possible
oxbow_lakes
Right, that's why the @Transactional annotations belong in the service layer, not in the persistence tier. Transactions are about units of work in use cases, which are represented by services.
duffymo
Yes - but the service layer may be tens of interfaces. I hadn't wanted to introduce dependencies on Spring to all of these. I think I'm softening to it now though
oxbow_lakes
I always put @Transactional at interface (service) implementations, not on the interfaces themselves. And those implementations are even packaged separately. So, some interface like UserManager imports only domain/business objects, while UserManagerImpl has Spring and Hibernate dependencies.
javashlook
javashlook is correct, the @Transactional annotations belong on the implementation, not the interface.
duffymo
A: 

I tend to be more of a purist, but I try to keep any and all transaction management beyond a simple autocommit, inside the database itself. Most databases are excellent at handling transaction management, after all, its one of the key components of what a database is meant to do.

Nick
The database is still doing it. How do you manage two-phase commit with this arrangement? There has to be a 3rd party that knows all the players, and that's the middle tier transaction manager.
duffymo
Exactly - the only way to do this properly is to move business logic inside the database. For example, insert-transaction/update-account must be "joined" together otherwise you'll end up with atomicity problems
oxbow_lakes
You mentioned nothing about a two-phase commit. You simple said database transaction management, which is much,much easier than a two-phase commit. If you need 2PC, Spring's @Transactional isn't gonna help you either.
Nick
+2  A: 

Regarding (1): I found @Transactonal a more practical solution in all projects worked on in the past few years. In some very specific cases, however, I had also to use Spring AOP to allow the use of more than one JDBC connection / TransactionManager because @Transaction is tied to a single transaction manager.

Regarding (2): Having said that, in a mixed scenario, I do a lot of automated testing to find possibly broken code. I use Spring's AbstractTransactionalJUnit4SpringContextTests / AbstractTransactionalTestNGSpringContextTests to create my tests. It's been a very effective solution so far.

Antonio