I work to correct the @CommitAfter problems. Since I have 'overwritten' the Tapestry HibernateManager class, I see the following behavior.
For every request a new session object is created and opened. So when you have something like this: myPage() { A: userService.getUserProfile(); B: locationService.updateLocationOfUser(); C: weatherService.getCurrentWeather(userService.getLocation(user)); } This is done inside a transaction and rolled back at the end. So now a coworker of yours forgot the @CommitAfter. Since the current implementation creates a new transaction when the session object is created, and when the session is closed the current transaction is aborted the transaction is: T1 = {A, B, C} + rollback Now the fun is on updateLocation the service stores the new location of the user inside the database and getCurrentWeather is using the location of the user. In your test case this is marked as correct since it is correct behavior. The location is updated and the correct weather is requested and shown. But in reality your code is broken since actually after that request the user location is not(!) permanently stored but aborted. So your workflow is down and you spent hours of debugging and reading. So now your coworker saw the problem and adds the annotation @CommitAfter to locationService.updateLocationOfUser. So what happens? you get T1 {A} + commit, T2{B} + commit, T3 {C} + rollback. Your unit test went through but actually you created a strange bug inside your application. Between B and C you have a window where your database might introduce a different location and your request which you expect as a single unit will be actually broken down into three independend transaction. Ok you can say its my fault and you might be right but we live in a test driven environment we dont want to design ahead even for transactions unless we do something stupid here. Also between those transactions we might use the Object from A wrongly it might contain staled data that are used in T2 and T3. So we have all sorts of problems. also I can do something like this: session.get(User), service.updateUser(requestInformation), session.flush(). And It works. I forgot to mark my new service method as transactional and it works. Since everytime tapestry creates a session a new transaction is started and everytime it aborts or commits a transaction a new one automatically begins. So there is no way tapestry prevent me from doing stupid things. You can blame it on me for sure. But that is not how the world works. Also with the current implementation you will never hit a slave in a Master/Slave SQL server setup. Since all transactions are marked as being able to write, you always hit the master server even if you are just going to use a read only access maybe even with a lower isolation level. Today I switched on strict transaction declaration. I can do nothing within a session (beside some status, connection, close etc) without a surrounding transaction. Also I may not nest write transaction inside a read only transaction (something that is possible now but results into two commits). Guess what. This solution reports bugs over bugs. It was done wrong several times. What appears to be one transaction were many. Including all sort of changes to introduce bugs that are a nightmare to analyse and find. Noone can get when your database gets corrupted because you now have three transactions instead of a single one because you called two service methods also being annotated @AfterCommit. This should be changed. Please do something about it. I had the same complain when I walked into this 2008 and now I walked into it again and it was not fixed. I consider the tapestry hibernate modul as being broken until this is fixed and I guess you might feel the same. Cheers, Martin (Kersten), Germany. PS: I know you dont like rebinding but we need it. There is no point in being not able to replace a already bind service implementation especially when it is introduced by a sub module. Also I was able to simply work around this. So please try to fix it also. I know the modules are bind in random order so a rebind might result into logically unsolvable problems. But please rething and try to offer a rebind. I would have needed one.