RESOLVED - issue SWF-378: Session binding conversation containers cannot be used in a cluster
http://opensource.atlassian.com/projects/spring/browse/SWF-378
This commit is contained in:
@@ -13,6 +13,7 @@ Package org.springframework.webflow.engine
|
||||
|
||||
Package org.springframework.webflow.execution
|
||||
* Made the Event class non-final to allow for extension (SWF-330).
|
||||
* Now allow multiple conversation containers per session in a manner that supports use in a cluster (SWF-378).
|
||||
|
||||
Changes in version 1.0.4 (13.06.2007)
|
||||
-------------------------------------
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.springframework.webflow.conversation.ConversationId;
|
||||
import org.springframework.webflow.conversation.ConversationManager;
|
||||
import org.springframework.webflow.conversation.ConversationParameters;
|
||||
import org.springframework.webflow.core.collection.SharedAttributeMap;
|
||||
import org.springframework.webflow.util.RandomGuid;
|
||||
import org.springframework.webflow.util.RandomGuidUidGenerator;
|
||||
import org.springframework.webflow.util.UidGenerator;
|
||||
|
||||
@@ -44,10 +43,14 @@ public class SessionBindingConversationManager implements ConversationManager {
|
||||
private static final Log logger = LogFactory.getLog(SessionBindingConversationManager.class);
|
||||
|
||||
/**
|
||||
* Generate a unique key for the session attribute holding the conversation container managed by this conversation
|
||||
* manager.
|
||||
* The name of the session attribute that will hold the conversation container used by this conversation manager.
|
||||
*
|
||||
* To support multiple independent conversation containers in the same web application, for example, for use with
|
||||
* multiple flow executors each configured with their own session-binding conversation manager, set this field's
|
||||
* value to something unique.
|
||||
* @see #setSessionKey(String)
|
||||
*/
|
||||
private final String sessionKey = "webflow.conversation.container." + new RandomGuid().toString();
|
||||
private String sessionKey = "webflow.conversationContainer";
|
||||
|
||||
/**
|
||||
* The conversation uid generation strategy to use.
|
||||
@@ -62,7 +65,6 @@ public class SessionBindingConversationManager implements ConversationManager {
|
||||
|
||||
/**
|
||||
* Returns the used generator for conversation ids. Defaults to {@link RandomGuidUidGenerator}.
|
||||
* @since 1.0.1
|
||||
*/
|
||||
public UidGenerator getConversationIdGenerator() {
|
||||
return conversationIdGenerator;
|
||||
@@ -77,7 +79,6 @@ public class SessionBindingConversationManager implements ConversationManager {
|
||||
|
||||
/**
|
||||
* Returns the maximum number of allowed concurrent conversations. The default is 5.
|
||||
* @since 1.0.1
|
||||
*/
|
||||
public int getMaxConversations() {
|
||||
return maxConversations;
|
||||
@@ -91,14 +92,23 @@ public class SessionBindingConversationManager implements ConversationManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key this conversation manager uses to store conversation data in the session. The key is unique for
|
||||
* this conversation manager instance.
|
||||
* Returns the key this conversation manager uses to store conversation data in the session.
|
||||
* @return the session key
|
||||
*/
|
||||
public String getSessionKey() {
|
||||
return sessionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key this conversation manager uses to store conversation data in the session. If multiple session
|
||||
* binding conversation managers are used in the same web application to back independent flow executors, this value
|
||||
* should be unique among them.
|
||||
* @param sessionKey the session key
|
||||
*/
|
||||
public void setSessionKey(String sessionKey) {
|
||||
this.sessionKey = sessionKey;
|
||||
}
|
||||
|
||||
public Conversation beginConversation(ConversationParameters conversationParameters) throws ConversationException {
|
||||
ConversationId conversationId = new SimpleConversationId(conversationIdGenerator.generateUid());
|
||||
if (logger.isDebugEnabled()) {
|
||||
|
||||
@@ -87,11 +87,15 @@ public class SessionBindingConversationManagerTests extends TestCase {
|
||||
conversation.putAttribute("testAttribute", "testValue");
|
||||
ConversationId conversationId = conversation.getId();
|
||||
ExternalContextHolder.setExternalContext(null);
|
||||
// simulate write out of session
|
||||
byte[] passiveSession = passivate(externalContext.getSessionMap());
|
||||
|
||||
// simulate start-up of server
|
||||
conversationManager = new SessionBindingConversationManager();
|
||||
String id = conversationId.toString();
|
||||
conversationId = conversationManager.parseConversationId(id);
|
||||
|
||||
// simulate restore of session
|
||||
externalContext.setSessionMap(activate(passiveSession));
|
||||
ExternalContextHolder.setExternalContext(externalContext);
|
||||
Conversation conversation2 = conversationManager.getConversation(conversationId);
|
||||
@@ -125,6 +129,14 @@ public class SessionBindingConversationManagerTests extends TestCase {
|
||||
assertNotNull(conversationManager.getConversation(conversation3.getId()));
|
||||
}
|
||||
|
||||
public void testCustomSessionKey() {
|
||||
conversationManager.setSessionKey("foo");
|
||||
MockExternalContext context = new MockExternalContext();
|
||||
ExternalContextHolder.setExternalContext(context);
|
||||
conversationManager.beginConversation(new ConversationParameters("test", "test", "test"));
|
||||
assertNotNull(context.getSessionMap().get("foo"));
|
||||
}
|
||||
|
||||
private byte[] passivate(SharedAttributeMap session) throws Exception {
|
||||
// session is serialized out
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
@@ -138,4 +150,4 @@ public class SessionBindingConversationManagerTests extends TestCase {
|
||||
return (SharedAttributeMap) new ObjectInputStream(new ByteArrayInputStream(sessionData)).readObject();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user