Hello everyone,
I'm using Spring's OpenSessionInViewFilter to allow lazy loading of Hibernate 
domain objects in my page class. Now the filter opens sessions are read only, 
and when I have to save something in my service bean, i get a "Write operations 
are not allowed in read-only mode (FlushMode.NEVER/MANUAL): Turn your Session 
into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction 
definition." Exception, which makes sense.
Now one solution for this is to open all sessions as read / write by extending 
this filter and overriding a couple of methods, which works, but seems like a 
bad idea considering the 90/10 Read/Write rule. 
So I decided to use @Transactional annotations on my service methods which need 
to save, and open a new Transaction. So I declared something like this.
@Transactional(propagation=Propagation.REQUIRES_NEW, readOnly=false)
above the method. Then in my context.xml i declared  <tx:annotation-driven 
transaction-manager="transactionManger"/> and then declared a transaction 
manager for my session. I'm using eclipse with Spring project nature and it 
immediately picks this up, and adds a little orange double arrow symbol next to 
this, and the service method.
But when I use it in the Page class, I still get the same exception, which 
leads me to believe that the proxy isn't being created. I looked at my logs and 
there is no indication of the TransactionManager being invoked.
In my page class, instead of injecting the service directly, I also tried 
injecting ApplicationContext and then using its getBean method, but that did 
not work either.
I tried the older approach, and declared transaction proxies for the beans like 
this.
<bean id="transactionManger" parent="baseTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
        </bean>
        
        <!-- Proxied Services -->
        
 <bean id="proxyTemplate" 
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" 
abstract="true">
        <property name="transactionManager" ref="transactionManger" /> 
                <property name="transactionAttributes">
                        <props>
                                <prop 
key="save*">PROPAGATION_REQUIRES_NEW</prop>
                                <prop 
key="*">PROPAGATION_SUPPORTS,readOnly</prop>
                        </props>
                </property>
        </bean>
        
        
 <bean id="enrollmentService" parent="proxyTemplate">
        <property name="enrollmentServiceTarget">
                <bean class="my.app.services.impl.EnrollmentServiceImpl">
                        <property name="enrollmentDao" ref="enrollmentDao" />
                        // Other injections for the service
                        </bean>
                </property>
        <property name="proxyInterfaces" 
value="my.app.services.EnrollmentService" />
        </bean>

And this does, work, and works very well at that. Looking at my logs I find
[DEBUG] interceptor.TransactionInterceptor Completing transaction for 
[my.app.services.EnrollmentService.methodName]
[DEBUG] hibernate3.HibernateTransactionManager Triggering beforeCommit 
synchronization
[DEBUG] hibernate3.HibernateTransactionManager Triggering beforeCompletion 
synchronization
[DEBUG] hibernate3.HibernateTransactionManager Triggering afterCommit 
synchronization
[DEBUG] hibernate3.HibernateTransactionManager Triggering afterCompletion 
synchronization

I haven't tried the spring / aop way of doing it, using <tx:advice> so I'm not 
sure if that would work.
So my question is, why don't annotated transactions work? Is there something I 
can do differently to get them working? Would I have to make some contributions 
in app.module when the ApplicationContext is created? Or is there something 
that I'm just doing wrong? Declaring them in XML is fine, except that it gets 
cluttered quickly and is less readable.
If anyone has any experience with this, or has any suggestions for me I would 
really appreciate it.
Thanks,Jeshurun

Reply via email to