|
From: Colin S. <col...@ex...> - 2003-09-28 20:30:12
|
Jürgen, (Now that you are back I can write some more 'frivolous' emails :-) ). W/regards to adding additional interceptor support to TransactionProxyFactoryBean, I'm not sure I fully agree that it's inherently better or 'cleaner' to apply these to transactional methods only. That is, when thinking, 'what is TransactionProxyFactoryBean (in this modified version)?', you could consider it as a variant of ProxyFactoryBean that implicitly applies a Transaction interceptor (before, after, or in between other interceptors, as we decide makes the most sense). Those other interceptors can themselves decide if they apply, as with ProxyFactoryBean... There is a usecase for calling Hibernate code (needing a session), without needing transactions, and that's mostly for read-only data (where there is no need for isolation provided by a transaction). I realize that I could just use a regular ProxyFactoryBean, but this is all about reducing by maybe 40-50% a bunch of almost identical context config data to set up the interceptors. In a decent size app, this is a lot of extra typing and maintenance. If the additional interceptors applied to only transactional methods, then you would on a case by case method have to decide whether or not to use ProxyFactoryBean or TransactionProxyFactory, or else always use the 'supports' transaction attribute, which doesn't seem that clean to me. Regards, Colin jürgen höller [werk3AT] wrote: >Hi Colin, > >Your issue is caused by the reliance of your Hibernate access code on HibernateInterceptor for correct resource opening and closing. You should apply HibernateInterceptor even when using HibernateTransactionManager, to be able to switch to JtaTransactionManager without hassle. > >Note that when using HibernateTemplate with allowCreate=true (the default), a new Session will automatically enlist itself with the transaction synchronization capabilities of JtaTransactionManager: It will be created on first access, reused throughout the current transaction, and closed on transaction completion. This guarantees correct JVM-level read-write caching with JTA, and seamless switching between HibernateTransactionManager and JtaTransactionManager. > >In your case, I would indeed have suggested to go the standard ProxyFactoryBean route and apply a HibernateInterceptor after the TransactionInterceptor (after is semantically clearer than before, IMO). ProxyFactoryBean is the correct choice for applying multiple interceptors. TransactionProxyFactoryBean is just meant for declarative transaction management without worrying about AOP concepts. > >Obviously, TransactionProxyFactoryBean could be extended to support additional interceptors for its target bean. I would restrict this to transactional methods though: Executing other methods with a Hibernate Session is really not the task of TransactionProxyFactory Bean - I consider a generic ProxyFactoryBean appropriate here. And you can always define methods as transactional but with propagation "supports" instead of "required". > >Such a hook in TransactionProxyFactoryBean should probably be modelled as "additionalInterceptors" property, taking a list of Interceptor instances, getting applied after the implicit TransactionInterceptor for transactional methods. This can take a HibernateInterceptor or JdoInterceptor or the like. Again, an additional HibernateInterceptors doesn't hurt even with HibernateTransactionManager - it will simply participate in the existing thread-binding. > >Juergen > > > -----Original Message----- > From: Colin Sampaleanu [mailto:col...@ex...] > Sent: Thu 9/4/2003 11:10 PM > To: spr...@li... > Cc: > Subject: [Springframework-developer] wrapping an interceptor and Hibernate specific TransactionProxyFactoryBean > > > > I was using the TransactionProxyFactoryBean with the > HibernateTransactionManager, but when I switched to the > JTATransactionManager, got bitten by the fact that I no longer had > anything creating a Hibernate session and binding it to the current > thread, as HibernateTransactionManager used to do by default. > > One verbose solution would have been to have gone back to the old > ProxyFactoryBean mechanism for handling transactions, and just stack a > HibernateInterceptor in front of the transaction interceptor. > > I decided instead to make a Hibernate specific verison of > TransactionProxyFactoryBean. All it does is take a new > HibernateInterceptor property, and in afterPropertiesSet add the > interceptor before the transaction one (however, unlike the transaction > one, it will execute on all invocations, since you may want to run some > methods with a hibernate session, but no transactions. > // allways invoke the Hibernate Interceptor > addInterceptor(hibernateInterceptor); > ... existing code to set up the Transaction interceptor > > Now my questions: > 1: is it worth checking something like this in? I made a cut and past > copy of TransactionProxyFactoryBean, and added the new property and > modified the afterPropertiesSet. Obviously, I could also have just > subclasses the existing class and overriden afterPropertiesSet. That's > probably a better choice, but maybe a bit more dangerous if something > changes in the parent method which is no longer called at all. > 2: is there a better way of doing this? I supposed I could have wrapped > the proxy in another proxy to add the hibernate interceptor. This would > not have required any code changes, but would have made for a lot more > typing in the context. Another option would be to add optional before > and after, 'always invoke' interceptor properties to the > TransactionProxyFactoryBean, so something like this can be added. > > Regards, > Colin > > |