Results 1 to 4 of 4

Thread: @Transactional Code Does Not Flush Unless OpenSessionInViewInterceptor is set To Auto

  1. #1

    Default @Transactional Code Does Not Flush Unless OpenSessionInViewInterceptor is set To Auto

    I've added an OpenSessionInViewInterceptor (OSIVI) to my code to allow my JSPs to access lazily loaded associations. I already had a transaction manager setup and my services make use of the @Transactional annotation. This still works well for reading but writing only works in non request code, e.g. bean initialisation code - unless I set the flush mode name to FLUSH_AUTO.

    I understand that the OSIVI does not auto flush by default. This is fine - my views only need to read, but from the documentation I thought that the code marked by @Transactional would continue to flush itself. Is my assumption wrong? Should I need to use FLUSH_AUTO?

    Interceptor and transaction manager:

    Code:
    <tx:annotation-driven />
    
    	<bean id="transactionManager"
    		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    		<property name="sessionFactory" ref="sessionFactory" />
    	</bean>
    	
    	<mvc:interceptors>
    		<bean id="openSessionInView"
    			class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
    			<property name="sessionFactory">
    				<ref bean="sessionFactory" />
    			</property>
    			<property name="flushModeName" value="FLUSH_AUTO"/>
    		</bean>
    	</mvc:interceptors>
    Without the AUTO FLUSH everything appeared to work without error except that nothing ever persisted.

  2. #2
    Join Date
    Aug 2006
    Posts
    113

    Default

    10,000 foot view... I would guess transactions are just not working at all for you.

    Please set a breakpoint inside your DAO code just after some kind of access to Hibernate/EntityManager. Then report the stack trace you see. Please then look through the call chain and explain which methods (or classes) have @Transactional set on them. I would be looking in the stack trace for the proxy that is setup around the Spring managed object object at the outer side of the transactional context.



    Maybe you need @Service over your service class. Which has the outer transactional method inside it with @Transational over it and has the Hibernate DAO injected into it via @Autowired. You may need in your configuration:

    <context:annotation-config />
    <context:component-scan base-package="foobar.pack.age.name" />

    I am not sure if just <tx:annotation-driven/> will work without showing you have configured a <bean ../> for the instance or have use the <context:component-scan .../> above. Neither of which you showed in your CODE snippet.



    <rant>
    Normal OSIV would allow multiple transactions to exist sequentially using the same Hibernate Session.


    I have claimed for sometime that the website transactional model should really be:

    In the Request/Controller phase: (read-only, read-only|read-write, commit|rollback)* [repeat as many times as wanted]

    The end of the controller should force commit/rollback as/if necessary, then a switch to read-only. Where the view is read-only (which is good practise IMHO).

    Although with JSP you can be doing read-write things with data in the view, after you create an application over a certain size you realize it is best to handle recovery from errors in the controller, so you can direct the view accordingly. So to benefit from Lazy loading you really want to lock down SQL access to read-only mode.
    </rant>

  3. #3

    Default

    Thanks for the helpful reply. My response is inline...

    Quote Originally Posted by dlmiles View Post
    10,000 foot view... I would guess transactions are just not working at all for you.
    That's not the case. As I mentioned in the original post the transactions are working for code called by the context, e.g. bean initialisation. It doesn't flush for code called as a result of an HTTP request - unless I set AUTO FLUSH on the OSIV bean - in which case those transactions work too.

    Quote Originally Posted by dlmiles View Post
    Please set a breakpoint inside your DAO code just after some kind of access to Hibernate/EntityManager. Then report the stack trace you see. Please then look through the call chain and explain which methods (or classes) have @Transactional set on them. I would be looking in the stack trace for the proxy that is setup around the Spring managed object object at the outer side of the transactional context.
    That's an interesting suggestion. I've never given that a go and I could really do with some more tools in the kit - thanks. I'll post the result in a bit.

    Quote Originally Posted by dlmiles View Post
    Maybe you need @Service over your service class. Which has the outer transactional method inside it with @Transational over it and has the Hibernate DAO injected into it via @Autowired. You may need in your configuration:
    All my service classes have @Service and methods marked with @Transactional and have hibernate DAOs injected into them - which is why the none session annotated transactions work - and the other HTTP transactions work with auto flush.

    Quote Originally Posted by dlmiles View Post
    <context:annotation-config />
    <context:component-scan base-package="foobar.pack.age.name" />
    I've got the component scan line in my config, but not the annotation-config line although I have annotation-driven. Is this enough?

    Quote Originally Posted by dlmiles View Post
    I am not sure if just <tx:annotation-driven/> will work without showing you have configured a <bean ../> for the instance or have use the <context:component-scan .../> above. Neither of which you showed in your CODE snippet.
    All this is present, which is why it works as mentioned. I tried to keep the code snippet down to a manageable size.

    Quote Originally Posted by dlmiles View Post
    <rant>
    Normal OSIV would allow multiple transactions to exist sequentially using the same Hibernate Session.


    I have claimed for sometime that the website transactional model should really be:

    In the Request/Controller phase: (read-only, read-only|read-write, commit|rollback)* [repeat as many times as wanted]


    The end of the controller should force commit/rollback as/if necessary, then a switch to read-only. Where the view is read-only (which is good practise IMHO).
    This is how I thought it should work from reading the documentation - is there some documentation that says otherwise?

    Quote Originally Posted by dlmiles View Post
    Although with JSP you can be doing read-write things with data in the view, after you create an application over a certain size you realize it is best to handle recovery from errors in the controller, so you can direct the view accordingly. So to benefit from Lazy loading you really want to lock down SQL access to read-only mode.
    </rant>

  4. #4
    Join Date
    Dec 2006
    Posts
    311

    Default

    Also make sure your dont have two copies of your beans one in app context one in your servlet context. If your doing a scan in both, you should black list the annotations in servletContext and only grab the ones you want, for example:

    Code:
    	<context:component-scan base-package="com.your.company" use-default-filters="false">
    		<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
    	</context:component-scan>

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •