Redirecting to Previous Long Running Conversations
trickyvail Sep 7, 2007 12:00 PMSeam 2.0.0.BETA1
I would like a shopping website that allows users to have multiple carts open in different browser windows at the same time. Seam's conversation model appears to provide a solution: use a long running conversation for each cart and nested conversations everywhere a regular application would use a conversation.
One of the problems is how to transparently connect a user back to their cart (most recently accessed session) if they leave the site and come back using a url without the conversation id? I've tried the following solution:
pages.xml (fragment): <page view-id="*" action="#{conversationManager.manage}"> ConversationManager.java: @Name("conversationManager") @Scope(ScopeType.SESSION) public class ConversationManager { private Stack<String> conversationStack = new Stack<String>(); public String manage() { Manager manager = Manager.instance(); HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest(); String conversationIdRequestParameter = httpServletRequest.getParameter(manager.getConversationIdParameter()); if(! manager.isLongRunningOrNestedConversation()) { ConversationEntries conversationEntries = ConversationEntries.instance(); if(conversationEntries.getConversationEntries().size() == 0) { manager.beginConversation(); conversationStack.push(Conversation.instance().getId()); } else if ( conversationEntries.getConversationEntries().size() > 0 && conversationIdRequestParameter == null ) { while(conversationStack.size() > 0) { String conversationId = conversationStack.pop(); ConversationEntry conversationEntry = conversationEntries.getConversationEntry(conversationId); if(conversationEntry != null) { conversationEntry.redirect(); } } } } else if(manager.isLongRunningConversation()) { try { if(conversationStack.peek() != Conversation.instance().getId()) { conversationStack.remove(Conversation.instance().getId()); conversationStack.push(Conversation.instance().getId()); } } catch(EmptyStackException e){} } return null; } }
For every view the manage method:
- begins a long running conversation for new sessions.
- for requests that have conversations but no conversation id, redirects to last accessed existing conversation.
I've not tested this extensively but it appears to work as intended.
Because the conversation holds the cart, its timeout should be set to a long span. However when creating nested conversations it would be preferable for them to have a short span. Here's where I've run into a problem. I can set the conversation timeout like so:
Conversation.instance().setTimeout(int);
but as soon as I go to the next page the timeout will be back to the default setting. I've would like to use an approach like:
ConversationEntries.instance().getConversationEntry("2").setTimeout(int);
which would set the ConversationEntry dirty, but this method is not visible.
Here are my questions:
=============================================
- How do you permanently change a conversation's timeout?
- Is there a better multiple cart solution without hijacking the seam conversation model? (e.g. storing the carts in the sesssion and creating management similar to conversations)
- If this is an acceptable solution would it be better implemented as a servlet filter instead of mapping an action to the "*" view in pages.xml?
=============================================
Thanks in advance for your feedback.
references:
http://www.jboss.com/index.html?module=bb&op=viewtopic&t=109084