Announcement Announcement Module
Collapse
No announcement yet.
Webflow Hibernate Persistence Context Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Webflow Hibernate Persistence Context

    I am working on research into the feasibility of going with an exposed domain model pattern in the most general sense (yes, i know, many call it an 'anti-pattern'). So what i'd like to know is how Spring Web Flow behaves when http session clustering is in play. Namely,

    1. Is there an entirely new persistence context created for the flow when traffic begins hitting the peer node ?

    2. Is there any way for Webflow to "know" about objects attached to the Hibernate Session and re-attach them ?

    I am assuming the answer to 2 is likely no, and that i'd have to be responsible to reattach them if not attached. I am also assuming the answer to number 1 is yes. But would like confirmation on this, or a link to documentation that explains all this.

    Has anyone tried a design approach as such ? Any feedback ? Should i be playing with this at all ?

  • #2
    I ran an experiment to test this out. I am using the Spring Webflow/JSF integration for SWF 2.0/JSF RI 1.2 and a Hibernate persistence context. Here is what i did.

    Here is my setup.

    1. Two tomcat instances with session clustering turned on.
    2. Apache webserver configured to load balance the two tomcat instances via mod_jk.
    3. A webflow inside of the two said tomcat instances that utilizes a Spring Webflow persistence context.

    Steps performed.

    1. Bootup both tomcat instances.
    2. Bootup the apache webserver.
    3. Attempt to access the webflow through the apache webserver.
    4. Spring Security associated with the webflow re-routes to the login page.
    5. Login providing proper credentials.
    6. Navigate to the webflow. No attached objects are read.
    7. Bring down the tomcat instance that has been serving the traffic until now.
    8. Click a link to navigate into the flow. (Apache webserver re-routes to the single running instance).
    9. An error happens in webflow when reading serialized data.

    Since there were no persistent objects read and stored in flow, conversation, view, or any other scope i temporarily commented out the persistence-context. And repeated the above steps. The difference is this time step 9 worked and i was routed to the view within the flow the link was intended to route me to. If this is a boundary case not intended to be supported, fine, but i'd think it shouldn't blow up like that. Can anyone provide clarification on what behavior should be displayed ?

    The above mentioned exception ........

    java.lang.IllegalStateException: unread block data
    java.io.ObjectInputStream$BlockDataInputStream.set BlockDataMode(ObjectInputStream.java:2324)
    java.io.ObjectInputStream.readObject0(ObjectInputS tream.java:1336)
    java.io.ObjectInputStream.defaultReadFields(Object InputStream.java:1908)
    java.io.ObjectInputStream.defaultReadObject(Object InputStream.java:479)
    org.springframework.webflow.core.collection.LocalA ttributeMap.readObject(LocalAttributeMap.java:331)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:585)
    java.io.ObjectStreamClass.invokeReadObject(ObjectS treamClass.java:946)
    java.io.ObjectInputStream.readSerialData(ObjectInp utStream.java:1809)
    java.io.ObjectInputStream.readOrdinaryObject(Objec tInputStream.java:1719)
    java.io.ObjectInputStream.readObject0(ObjectInputS tream.java:1305)
    java.io.ObjectInputStream.readObject(ObjectInputSt ream.java:348)
    org.springframework.webflow.engine.impl.FlowSessio nImpl.readExternal(FlowSessionImpl.java:147)
    java.io.ObjectInputStream.readExternalData(ObjectI nputStream.java:1755)
    java.io.ObjectInputStream.readOrdinaryObject(Objec tInputStream.java:1717)
    java.io.ObjectInputStream.readObject0(ObjectInputS tream.java:1305)
    java.io.ObjectInputStream.readObject(ObjectInputSt ream.java:348)
    java.util.LinkedList.readObject(LinkedList.java:77 6)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    java.lang.reflect.Method.invoke(Method.java:585)
    java.io.ObjectStreamClass.invokeReadObject(ObjectS treamClass.java:946)
    java.io.ObjectInputStream.readSerialData(ObjectInp utStream.java:1809)
    java.io.ObjectInputStream.readOrdinaryObject(Objec tInputStream.java:1719)
    java.io.ObjectInputStream.readObject0(ObjectInputS tream.java:1305)
    java.io.ObjectInputStream.readObject(ObjectInputSt ream.java:348)
    org.springframework.webflow.engine.impl.FlowExecut ionImpl.readExternal(FlowExecutionImpl.java:513)
    java.io.ObjectInputStream.readExternalData(ObjectI nputStream.java:1755)
    java.io.ObjectInputStream.readOrdinaryObject(Objec tInputStream.java:1717)
    java.io.ObjectInputStream.readObject0(ObjectInputS tream.java:1305)
    java.io.ObjectInputStream.readObject(ObjectInputSt ream.java:348)
    org.springframework.webflow.execution.repository.s napshot.SerializedFlowExecutionSnapshot.deserializ e(SerializedFlowExecutionSnapshot.java:193)
    org.springframework.webflow.execution.repository.s napshot.SerializedFlowExecutionSnapshot.unmarshal( SerializedFlowExecutionSnapshot.java:98)
    org.springframework.webflow.execution.repository.s napshot.SerializedFlowExecutionSnapshotFactory.res toreExecution(SerializedFlowExecutionSnapshotFacto ry.java:80)
    org.springframework.webflow.execution.repository.s napshot.AbstractSnapshottingFlowExecutionRepositor y.restoreFlowExecution(AbstractSnapshottingFlowExe cutionRepository.java:89)
    org.springframework.webflow.execution.repository.i mpl.DefaultFlowExecutionRepository.getFlowExecutio n(DefaultFlowExecutionRepository.java:104)
    org.springframework.webflow.executor.FlowExecutorI mpl.resumeExecution(FlowExecutorImpl.java:162)
    org.springframework.webflow.mvc.servlet.FlowHandle rAdapter.handle(FlowHandlerAdapter.java:173)
    org.springframework.web.servlet.DispatcherServlet. doDispatch(DispatcherServlet.java:875)
    org.springframework.web.servlet.DispatcherServlet. doService(DispatcherServlet.java:807)
    org.springframework.web.servlet.FrameworkServlet.p rocessRequest(FrameworkServlet.java:571)
    org.springframework.web.servlet.FrameworkServlet.d oGet(FrameworkServlet.java:501)
    javax.servlet.http.HttpServlet.service(HttpServlet .java:617)
    javax.servlet.http.HttpServlet.service(HttpServlet .java:717)
    org.apache.myfaces.webapp.filter.ExtensionsFilter. doFilter(ExtensionsFilter.java:301)
    filters.RequestDumperFilter.doFilter(RequestDumper Filter.java:167)
    org.springframework.security.util.FilterChainProxy $VirtualFilterChain.doFilter(FilterChainProxy.java :378)
    org.springframework.security.intercept.web.FilterS ecurityInterceptor.invoke(FilterSecurityIntercepto r.java:109)
    org.springframework.security.intercept.web.FilterS ecurityInterceptor.doFilter(FilterSecurityIntercep tor.java:83)
    org.springframework.security.util.FilterChainProxy $VirtualFilterChain.doFilter(FilterChainProxy.java :390)
    org.springframework.security.ui.SessionFixationPro tectionFilter.doFilterHttp(SessionFixationProtecti onFilter.java:67)
    org.springframework.security.ui.SpringSecurityFilt er.doFilter(SpringSecurityFilter.java:53)
    org.springframework.security.util.FilterChainProxy $VirtualFilterChain.doFilter(FilterChainProxy.java :390)
    org.springframework.security.ui.ExceptionTranslati onFilter.doFilterHttp(ExceptionTranslationFilter.j ava:101)
    org.springframework.security.ui.SpringSecurityFilt er.doFilter(SpringSecurityFilter.java:53)
    org.springframework.security.util.FilterChainProxy $VirtualFilterChain.doFilter(FilterChainProxy.java :390)
    org.springframework.security.providers.anonymous.A nonymousProcessingFilter.doFilterHttp(AnonymousPro cessingFilter.java:105)
    org.springframework.security.ui.SpringSecurityFilt er.doFilter(SpringSecurityFilter.java:53)
    org.springframework.security.util.FilterChainProxy $VirtualFilterChain.doFilter(FilterChainProxy.java :390)
    org.springframework.security.ui.rememberme.Remembe rMeProcessingFilter.doFilterHttp(RememberMeProcess ingFilter.java:116)
    org.springframework.security.ui.SpringSecurityFilt er.doFilter(SpringSecurityFilter.java:53)
    org.springframework.security.util.FilterChainProxy $VirtualFilterChain.doFilter(FilterChainProxy.java :390)
    org.springframework.security.wrapper.SecurityConte xtHolderAwareRequestFilter.doFilterHttp(SecurityCo ntextHolderAwareRequestFilter.java:91)
    org.springframework.security.ui.SpringSecurityFilt er.doFilter(SpringSecurityFilter.java:53)
    org.springframework.security.util.FilterChainProxy $VirtualFilterChain.doFilter(FilterChainProxy.java :390)
    org.springframework.security.ui.basicauth.BasicPro cessingFilter.doFilterHttp(BasicProcessingFilter.j ava:174)
    org.springframework.security.ui.SpringSecurityFilt er.doFilter(SpringSecurityFilter.java:53)
    org.springframework.security.util.FilterChainProxy $VirtualFilterChain.doFilter(FilterChainProxy.java :390)
    org.springframework.security.ui.AbstractProcessing Filter.doFilterHttp(AbstractProcessingFilter.java: 277)
    org.springframework.security.ui.SpringSecurityFilt er.doFilter



    The webflow configuration .......

    <?xml version="1.0" encoding="UTF-8"?>
    <flow xmlns="http://www.springframework.org/schema/webflow"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/webflow
    http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

    <secured attributes="ROLE_USER"/>
    <persistence-context />

    <var name="jsfDocumentBackingBean" class="com.openfunctionality.teammanager.component s.documentmanager.ResourceDocumentManagerBackingBe an"/>

    <on-start>
    <evaluate expression="jsfDocumentBackingBean.setRootCategori es(documentManager.getRootCategories())"/>
    </on-start>

    <view-state id="displayDocuments" view="views/displayDocuments.jsp">
    <transition on="toggle" to="displayDocuments">
    </transition>
    <transition on="subcategoryAdded" to="displayDocuments">
    </transition>
    <transition on="rootCategoryAdded" to="displayDocuments">
    </transition>
    <transition on="resourceAdded" to="displayDocuments">
    </transition>
    </view-state>

    </flow>

    Comment


    • #3
      Dear Mr. Joe Rust,

      I tried something similar to your experiment. I implemented a mechanism to store the spring web flow "user conversation" in a database with relative success. I didn't use cluster (not yet), but it was my original intention. Indeed, this is the goal of this mechanism.

      Nevertheless, when I restart the tomcat (while testing the persisted conversation) I got this error (java.lang.IllegalStateException: unread block data), despite the conversation is in the db. If I don't restart the server, the app works fine with the db persisted conversation solution, even with Hibernate Persistence Context.

      Did you get some answers to it?

      Thanks in advance and sorry my english faults.

      Tiago Peixoto

      Comment


      • #4
        having the same problem ...

        ... using Webflow 2.0.9, Hibernate, Tomcat and Clustering via Tomcat's own PersistentManager

        org.apache.catalina.session.PersistentManager

        We are storing our sessions in a mysql-database. This works just fine... except when we use FlowBasedPersistence to manage the HibernateSession.

        In this case, whenever we restart one of the two Tomcats which form the cluster (and thus force a switch between the two), we get an "IllegalStateException" as following:

        org.springframework.web.util.NestedServletExceptio n: Request processing failed; nested exception is java.lang.IllegalStateException: unread block data
        org.springframework.web.servlet.FrameworkServlet.p rocessRequest(FrameworkServlet.java:583)
        org.springframework.web.servlet.FrameworkServlet.d oPost(FrameworkServlet.java:511)
        javax.servlet.http.HttpServlet.service(HttpServlet .java:637)
        javax.servlet.http.HttpServlet.service(HttpServlet .java:717)
        org.springframework.web.filter.CharacterEncodingFi lter.doFilterInternal(CharacterEncodingFilter.java :96)
        org.springframework.web.filter.OncePerRequestFilte r.doFilter(OncePerRequestFilter.java:76)
        org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(Base XMLFilter.java:178)
        org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseF ilter.java:290)
        org.ajax4jsf.webapp.BaseFilter.processUploadsAndHa ndleRequest(BaseFilter.java:368)
        org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter .java:495)

        Any idea what we are doing wrong? Or do you need any additional information?

        Greetings,

        Duskstrider

        Comment


        • #5
          Hi,

          my solution:

          Every tomcat instance in cluster has its own hibernate sessionFactory. Every hibernate Session is created with uuid of its parent sessionFactory (hibernate session holds this uuid).
          During session restoring process on another tomcat instance, hibernate is looking for hibernate sessionFactory with uuid contained in transported hibernate session. Hibernate sessionFactory with this uuid obviously doesn't exists.

          One possible workaround is to set the name of hibernate sessionFactory in your hibernate configuration.

          Code:
          <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
           <property name="dataSource" ref="dataSource"/>
            <property name="hibernateProperties">
             <value>
              hibernate.dialect=${hibernate.dialect}
              hibernate.session_factory_name=${hibernate.session_factory_name}
             </value>
            </property>
            <property name="mappingLocations">
             <list>
              <value>classpath*:hibernate/mappings/*/*.hbm.xml</value>
             </list>
           </property>
          </bean>
          If sessionFactory has the name set, every tomcat instance has hibernate sessionFactory with the same name. Hibernate looks for sessionFactory based on the name of the sessionFactory (not uuid) and that's why the sessionFactory is found.

          slovi

          Comment


          • #6
            This worked for me too. Thank you so much!

            Comment


            • #7
              Hi,

              I'm Having a very similar problem but I'm using grails webflow plugin 2.0.0.RC1 . Since grails doesn't have the same xml configuration system, do you know where do I have to put this configuration to work? some code snippet would be great!

              Thank you very much.

              Trygve.

              Comment

              Working...
              X