Page 1 of 3 123 LastLast
Results 1 to 10 of 24

Thread: OpenSessionInView for WebFlow

  1. #1
    Join Date
    Feb 2008
    Location
    Kharkov, Ukraine
    Posts
    64

    Default OpenSessionInView for WebFlow

    As I understand, the only way to have open hibernate session in view with SWF is using flow managed persistence (<persistence-context/> tag).

    OpenSessionInViewInterceptor allows only to have single session in flow controller, but in view it has no sence because of using Post+Redirect+Get pattern (there is a new http request for view rendering, so there is a new hibernate session). Even for this purpose (having single session in flow controllers for non <persistence-context> flows) is impossible because when there is at least one <persistence-context> flow, the application fails when entering this flow.

    Marking all flows where I need open session in view as <persistence-context/> I can't beacuse there many issues appear.

    So my question is:
    Is it possible to create some XXXFlowExecutionListener that will work the same as OpenSessionInViewInterceptor, but close session after view rendering? Flows marked as <persistence-context/> it should walk around.

    Any thoughts are welcome

  2. #2
    Join Date
    Feb 2008
    Location
    Kharkov, Ukraine
    Posts
    64

    Default

    I really like SWF 2 and use it in a quite big project because of it's navigational features, sophisticated controllers, Spring and JSF cool integration.

    But the persistence is the main problem with SWF for me now. We use native Hibernate with DAO pattern because there sometimes quite complex business logic when saving and loading objects needed. On the web-pages we need to show much detailed info contained not only in the loaded object, but in it's related objects which are lazily assotiated.

    I know only 3 ways to show those fields:
    1. Use lazy="false" associations
    2. Prefetch associated objects when loading the object while session isn't closed
    3. Use <persistence-context/>

    The first approach is the simplest, but for a big project will cause great performance issues because of huge amount of objects loaded even when they aren't really needed.

    The second approach isn't very convenient because you need every time write redundant code for loading associated objects needed fo the certain view.

    The third approach is good only when suporting some steps interface in single flow with single transaction or rollback at the end of the flow. But when there are two flows both marked as <persistence-context/>, and the first one calls the second as a subflow, there are situations when issues appear after returning to the first flow. Here are some of them:
    1. The session in the first flow remains the same and it can't get changes made by the subflow (showing cached objects)
    2. When to the object given to sublow into it's collection we attach some new persistent object, when returning to the first flow we get an exception because that object is associated with another session.
    3. Sometimes changes made in loaded objects are being persisted even when it isn't needed. I know it should be solved by using @Transational(readOnly=true) when laoding those objects, but sometimes this doen't help by unknown reason.

    Actually now we combine all of those approaches individaully for each module of the application in order to get it working. But I wouldn't say it's very convenient. I really would take a look on the conversation-scoped persistence contexts and view state persistence when they are implemented, but I don't think they will solve all those persistence problems.

    So the question remains the same, is it possible to have simple persistence support, allowing the single session for single user request (I mean form submit + controller execution + redirect + view rendering) in order to show lazy fields on the view? In all other situations working with detached objects I consider as satisfactorily.

    Thanks for any comments .
    Last edited by and; Sep 18th, 2008 at 02:58 AM. Reason: changed "readOnly=false" into "readOnly=true", it was misprint

  3. #3
    Join Date
    Mar 2008
    Posts
    170

    Default

    I have experienced the same issues. Additionally to your points I had problems that the session was closed after calling a subflow and that a class called org.hibernate.util.MarkerObject used by Hibernate (sometimes) can not be serialized.

    Quote Originally Posted by and View Post
    1. The session in the first flow remains the same and it can't get changes made by the subflow (showing cached objects)
    In case a commit of the subflow data is not a problem I reload the data in the on-render element of the parent flow (fetching data again after subflow has ended).
    You could also consider to merge an output of the subflow into the persistenceContext of the parent flow (I can remember to have tried it but there was some problem which I can't remember).

    Quote Originally Posted by and View Post
    3. Sometimes changes made in loaded objects are being persisted even when it isn't needed. I know it should be solved by using @Transational(readOnly=false) when laoding those objects, but sometimes this doen't help by unknown reason.
    It should be @Transational(readOnly=true) to tell Hibernate not to flush the changes in the persistenceContext. In general I'm using the
    Code:
    @Transactional(propagation=Propagation.REQUIRED, readOnly=true)
    on the class definition level and mark the methods which have to trigger a commit with
    Code:
    @Transactional(propagation=Propagation.REQUIRED, readOnly=false).
    Because I have a lot of database changes without leaving the view definition (Ajax) I do not have a commit at the end-state because my changes are committed by the methods marked as readOnly=false.
    I have not tried to mark everything as readOnly=false and have a commit in the end-state, I just (ab)use the <persistence-context> for lazy-loading (it was the only solution which was working for me).

    In case somebody knows a more elegant way to just have lazy-loading I'm happy to hear!

    - Peter

  4. #4
    Join Date
    Sep 2008
    Posts
    6

    Default

    @and
    I had the same problem with your #2

    2. When to the object given to sublow into it's collection we attach some new persistent object, when returning to the first flow we get an exception because that object is associated with another session.
    I solved it merging the output of the subflow into the persistenceContext of the parent flow like iwtolall said.
    I also tried to make an abstract flow where I declare the persistence context and inherit it in the 2 flows (main flow and subflow), but it didn't work and I don't know why. When I commit in the main flow the objects created in the subflow become detached. Why didn't this worked??

  5. #5
    Join Date
    Feb 2008
    Location
    Kharkov, Ukraine
    Posts
    64

    Default

    Quote Originally Posted by mirtzi View Post
    I also tried to make an abstract flow where I declare the persistence context and inherit it in the 2 flows (main flow and subflow), but it didn't work and I don't know why. When I commit in the main flow the objects created in the subflow become detached. Why didn't this worked??
    I think it's because the flow inheritance is provided on the metadata (flow definition) level. It means that every flow execution instance created on the base of it's flow definition has it's own varaible instances and persitence context. Just like in java: when you declare some attribute in superclass, create two subclasses and than it's instances, they (instances) have different instances of that attribute.

  6. #6
    Join Date
    Feb 2008
    Location
    Kharkov, Ukraine
    Posts
    64

    Default

    I've created JIRA issue for simple open session in view.
    http://jira.springframework.org/browse/SWF-893

    Those who interested in this feature please vote on it.

  7. #7
    Join Date
    Jun 2007
    Location
    Dublin, Ireland
    Posts
    72

    Default

    I'm not sure that I totally understand the problem as outlined. Ill give my two cents worth though.

    During the execution of a flow you can use the persistence-context element. This associates an entity manager with the current executing thread. All spring DAO have access to this entity manager and use it for persistence operations. The entity manager is retained for the duration of the flow, not just the request.

    If you do not use this you can use the open session in view pattern. This does exactly the same as persistence-context except the entity manager is only retained for the duration of the request. When the request is completed all entities become detached and the entity manager is discarded.

    If using post-redirect-get, you will have to merge the entity into the new persistence context (entity manager) before instantiating any lazy associations etc.

  8. #8
    Join Date
    Feb 2008
    Location
    Kharkov, Ukraine
    Posts
    64

    Default

    Quote Originally Posted by turnerj View Post
    If using post-redirect-get, you will have to merge the entity into the new persistence context (entity manager) before instantiating any lazy associations etc.
    I mean it would be convenient if the same entity manager (hibernate session) was accessible diring the single post+redirect+get browser-server conversation, so we could access lazy associations without deatching and merging persistent objects. It would be something between flow managed persistance approach and ordinal OpenSessionInView approach.

  9. #9
    Join Date
    Jun 2007
    Location
    Dublin, Ireland
    Posts
    72

    Default

    Have you tried to use persistence-context and the redirect options outlined on page 54 of the user guide?

    I have not used this but would have thought it would work?

  10. #10
    Join Date
    Jun 2007
    Location
    Dublin, Ireland
    Posts
    72

    Default

    Actually, I'll correct myself. It looks like when you do a redirect you are no longer executing the flow instance.

    But if this is the case, how are you getting the entity within the view? Did you put in into the session within the flow?

Posting Permissions

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