[ https://issues.apache.org/struts/browse/WW-1514?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Tom Schneider reassigned WW-1514: --------------------------------- Assignee: Tom Schneider > Conversation Scope > ------------------ > > Key: WW-1514 > URL: https://issues.apache.org/struts/browse/WW-1514 > Project: Struts 2 > Issue Type: New Feature > Components: Core Interceptors > Reporter: Mark Menard > Assignee: Tom Schneider > Priority: Minor > Fix For: 2.1.1 > > Attachments: ConversationModelDriven.java, > ConversationModelInterceptor.java, ConversationScopeAware.java, > ConversationScopeInterceptor.java > > > Problem: A user may need to, or be able to use, multiple tabs on the same > work flow process, using different data, that would usually be stored in the > user's session. The problem is if you use the Session scope you can only have > one version of the users data in memory. This can result in a "crossing of > the streams" between their two (or more) independent work flows. Ad-hoc > solutions on a per action basis could be implemented, but this is awkward at > best. > Example: User opens two processes of the same type, using the same action(s), > in separate tabs in their browser, working on independent data sets. Each > data model must be stored separately in their session. > Solution: Implement a "Conversation Scope" using an Interceptor and a marker > interface for Actions to implement that will transparently manage multiple > independent conversations of the same type on independent data sets. > ConversationScopeInterceptor: This interceptor does the hard lifting. It > maintains a conversationMap in each users session that allows for the storage > of multiple converstaionModels. The conversationModels are keyed using an > incrementing int, and the current time in milliseconds when the conversation > began. The incrementing of the conversation counter is synchronized. > Additionally the interceptor pushes the conversationModel onto the ValueStack > much the same way as ModelDriven pushes the model onto the ValueStack. > ConversationScopeAware: This is a marker interface for Actions to implement. > It includes methods to set/get the conersationId, set/get/prepare the > conversationModel. prepareConversationModel() is called at the start of a > conversation and allows the action to prepare the data model the user will be > working with over the conversation. > Motivation: The major motivation for this was work that we did in Struts 1 to > work around the pervasive use of session forms. We realized that users could > cross the streams with multiple forms in memory. To work around this we > created a deep Action hierarchy that handled swapping the "conversation" data > into and out of a Map backed form. Although Struts 2 does not suffer from the > same pervasive need to use session forms there are times when a conversation > is needed and with modern browsers and the wide usage of tabs, it is just a > matter of time before a user opens two tabs on the same type of conversation. > View requirements: In order to track the conversation the HTML form must > contain: > <input type="hidden" name="S2_CONVERSATION_ID" value="<the_current > conversation_id"> > The current conversation id is available as a property of any Action that > implements ConversationScopeAware and can be included with the following: > <s:hidden name="S2_CONVERSATION_ID" value="%{conversationId}" /> > Possible Improvements: Slip stream this right into ModelAware, and just use > getModel() from the ModelAware interface and supplement it with set and > prepare methods. I didn't want to do that initially because I'm not sure it > would be appropriate, nor do I like non-explicit things. It would make moving > a model aware action to a conversation model scope easier, but using > coversationModel just means changing getModel() to getConversationModel() in > your action. > Additionally this could be improved by setting the conversatonId onto the > ValueStack, and retrieving it off the stack in the view. This would allow for > the removal of the get/setConversationId() from the ConversationScopeAware > interface. I just couldn't figure out how to do that. -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.