Struts 1
  1. Struts 1
  2. STR-2939

Provide a conversation scope (syn: Flash scope, dialog scope) object to store data between requests.

    Details

    • Type: Improvement Improvement
    • Status: In Progress
    • Priority: Minor Minor
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: Future
    • Component/s: Core
    • Labels:
      None

      Description

      In addition to standard J2EE scopes (page for JSP, request, session and application) provide a new scope object that would hold data between requests. Similar facilities in Tapestry and Stripes are called FlashScope, Struts 1 will call it as Conversation Scope.

      Physically, this object will be stored in the session object. It will allow the same get/set/remove operations as other scopes. The objects placed in this scope will be removed two roundtrips after they were placed (they are intended to be used after the first roundtrip). The object lifetime can be increased by increasing a corresponding roundtrip counter.

      Struts 1.2.x introduced storing messages in the session with their automatic cleanup after they are used, usually in a JSP page. Therefore, Struts 1.2.x has a rudimentary Conversation Scope for messages only. Retrofit mesage handling, queue messages to Conversation scope.

      • Provide direct access to Conversation scope from Action (create a method)
      • Update saveMessages to accept Conversation scope
      • For classes other than Action provide an utility method in RequestUtils
      • Allow using Conversation scope in an action mapping definition for ActionForms.

      From developer's point of view usage of ActionForms in Conversation scope + redirect to view should be similar to usage of ActionForms in request scope and forwarding to view. Ideally it should be possible to retrofit statelless actions that forward to JSPs to Conversation actions that redirect to views by only changing the scope of an ActionForm in an action mapping.

      What the whole thing is for? To be able to use redirection without worrying about garbage in the session. Redirection allows to provide better user experience, in particular related to navigation and double submit.

        Issue Links

          Activity

          Hide
          Paul Benedict added a comment -

          Pushing to Future until Michael returns (if ever?)

          Show
          Paul Benedict added a comment - Pushing to Future until Michael returns (if ever?)
          Hide
          Michael Jouravlev added a comment -

          See http://wiki.apache.org/struts/RolloverScope for description and samples.

          Show
          Michael Jouravlev added a comment - See http://wiki.apache.org/struts/RolloverScope for description and samples.
          Hide
          Michael Jouravlev added a comment -

          [[ Old comment, sent by email on Thu, 31 Aug 2006 14:00:53 -0700 ]]

          Ok, I have implemented a first draft.

          [1]

          First, the name. I chose the one that I think is a pretty good one:
          Rollover Scope. Meaning that request-scoped data rolls over to a next
          request. The name is final, no alternative names please The name
          describes the functionality and at the same time does not give a wrong
          impression that it somehow related to wizards, dialogs, flow, etc. On
          the other hand, a wizard that uses rollover scope for its ActionForm
          works pretty well

          [2]

          Now the functionality. The rollover scope can be accessed from Action
          with a member method, it can also be accessed by reading an object
          from HttpServletRequest keyed as ROLLOVER_KEY.

          Everything written to rollover scope is written to the request object
          too, everything read from rollover scope is looked up in request
          object first, then if not found, it is looked up in rollover object
          itself. This way rollover data is presented to other parts of
          application including JSP tags as regular request-scoped data.

          Rollover scope is implemented in the new composable request processor
          both for commands and actions. Rollover scope is supported for action
          mappings as well, so an action mapping can use scope="rollover". Here
          is an example of a login component implemented with two action
          mappings and two corresponding actions.

          <action path = "/logininputaction"
          type = "com.acme.LoginInputAction"
          name = "loginform"
          scope = "rollover"
          validate = "false"
          parameter = "initEvent=init,loginEvent=login,logoutEvent=logout">
          <forward name = "render" path = "/loginrenderaction.do" redirect = "true"/>
          </action>

          <action path = "/loginrenderaction"
          type = "com.acme.LoginRenderAction"
          name = "loginform"
          scope = "request"
          validate = "false">
          <forward name = "notloggedin" path = "/pages/login.jsp"/>
          <forward name = "loggedin" path = "/pages/logout.jsp"/>
          </action>

          Login component is normally accessed with "loginrenderaction" URL.
          When a user navigates to this location, LoginRenderAction checks
          current user stored in the session, and displays either login.jsp page
          if no one is logged in, or logout.jsp if there is a logged in user.

          login.jsp contains a login form that submits to "logininputaction",
          LoginInputAction uses loginform to store username (password is not
          stored) in case it has to be redisplayed when credentials are not
          correct. When a user submits a form for the first time, Struts checks
          whether the loginform exists, it does not, so it creates a form in
          rollover scope. After username/password are checked, a user is either
          logged in or not, but in both cases he is redirected to
          loginrenderaction that either redisplays a login page or shows current
          login status. Before the redirection, the loginform is pushed from
          request to session because it is defined in rollover scope for
          logininputaction.

          On the next request the form is pulled from the session into the
          request, but not into the rollover scope. "loginrenderaction"
          redisplays the login page along with error message and shows the login
          name entered on previous attempt. Because loginrenderaction defines
          the form as request-scoped (see mapping above), the loginform is not
          stored in rollover scope, now it is a regular request-scoped form. So
          when a user hits "refresh", the form is automatically recreated by
          Struts, so the entered username is gone. To prevent this, the form
          should be defined with scope="rollover" in both input and render
          mappings, this way it will always be saved in the session when request
          comes. This allows to refresh the page without losing data.

          At the same time, if a user navigates to another page and then comes
          back to login page, the entered username will be lost because the
          loginform will be recreated. I think this is acceptable for cases like
          login.

          [3]

          Now I am going to add temporary cookies that will identify a rollover
          scope, this way one will be able to have as many rollover scopes as
          many browser windows are open. The cookie is chosen instead of a
          request parameter (like in Stripes) because I want to preserve the URL
          intact, it may matter if a developer cares about browser page history.
          Thanks Antonio for the tips on storing rollover scope in the request
          and on using cookies.

          Comments?

          Michael.

          Show
          Michael Jouravlev added a comment - [[ Old comment, sent by email on Thu, 31 Aug 2006 14:00:53 -0700 ]] Ok, I have implemented a first draft. [1] First, the name. I chose the one that I think is a pretty good one: Rollover Scope. Meaning that request-scoped data rolls over to a next request. The name is final, no alternative names please The name describes the functionality and at the same time does not give a wrong impression that it somehow related to wizards, dialogs, flow, etc. On the other hand, a wizard that uses rollover scope for its ActionForm works pretty well [2] Now the functionality. The rollover scope can be accessed from Action with a member method, it can also be accessed by reading an object from HttpServletRequest keyed as ROLLOVER_KEY. Everything written to rollover scope is written to the request object too, everything read from rollover scope is looked up in request object first, then if not found, it is looked up in rollover object itself. This way rollover data is presented to other parts of application including JSP tags as regular request-scoped data. Rollover scope is implemented in the new composable request processor both for commands and actions. Rollover scope is supported for action mappings as well, so an action mapping can use scope="rollover". Here is an example of a login component implemented with two action mappings and two corresponding actions. <action path = "/logininputaction" type = "com.acme.LoginInputAction" name = "loginform" scope = "rollover" validate = "false" parameter = "initEvent=init,loginEvent=login,logoutEvent=logout"> <forward name = "render" path = "/loginrenderaction.do" redirect = "true"/> </action> <action path = "/loginrenderaction" type = "com.acme.LoginRenderAction" name = "loginform" scope = "request" validate = "false"> <forward name = "notloggedin" path = "/pages/login.jsp"/> <forward name = "loggedin" path = "/pages/logout.jsp"/> </action> Login component is normally accessed with "loginrenderaction" URL. When a user navigates to this location, LoginRenderAction checks current user stored in the session, and displays either login.jsp page if no one is logged in, or logout.jsp if there is a logged in user. login.jsp contains a login form that submits to "logininputaction", LoginInputAction uses loginform to store username (password is not stored) in case it has to be redisplayed when credentials are not correct. When a user submits a form for the first time, Struts checks whether the loginform exists, it does not, so it creates a form in rollover scope. After username/password are checked, a user is either logged in or not, but in both cases he is redirected to loginrenderaction that either redisplays a login page or shows current login status. Before the redirection, the loginform is pushed from request to session because it is defined in rollover scope for logininputaction. On the next request the form is pulled from the session into the request, but not into the rollover scope. "loginrenderaction" redisplays the login page along with error message and shows the login name entered on previous attempt. Because loginrenderaction defines the form as request-scoped (see mapping above), the loginform is not stored in rollover scope, now it is a regular request-scoped form. So when a user hits "refresh", the form is automatically recreated by Struts, so the entered username is gone. To prevent this, the form should be defined with scope="rollover" in both input and render mappings, this way it will always be saved in the session when request comes. This allows to refresh the page without losing data. At the same time, if a user navigates to another page and then comes back to login page, the entered username will be lost because the loginform will be recreated. I think this is acceptable for cases like login. [3] Now I am going to add temporary cookies that will identify a rollover scope, this way one will be able to have as many rollover scopes as many browser windows are open. The cookie is chosen instead of a request parameter (like in Stripes) because I want to preserve the URL intact, it may matter if a developer cares about browser page history. Thanks Antonio for the tips on storing rollover scope in the request and on using cookies. Comments? Michael.

            People

            • Assignee:
              Unassigned
              Reporter:
              Michael Jouravlev
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:

                Development