Author: nickarls
Date: 2010-02-27 08:31:35 -0500 (Sat, 27 Feb 2010)
New Revision: 5964
Added:
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationManager.java
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ManagedConversation.java
Removed:
api/trunk/weld/src/main/java/org/jboss/weld/conversation/ConversationManager.java
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationEntry.java
Modified:
api/trunk/weld/src/main/java/org/jboss/weld/conversation/ConversationIdGenerator.java
core/trunk/impl/src/main/java/org/jboss/weld/context/ContextLifecycle.java
core/trunk/impl/src/main/java/org/jboss/weld/context/ConversationContext.java
core/trunk/impl/src/main/java/org/jboss/weld/context/beanstore/AbstractAttributeBackedBeanStore.java
core/trunk/impl/src/main/java/org/jboss/weld/context/beanstore/HashMapBeanStore.java
core/trunk/impl/src/main/java/org/jboss/weld/conversation/AbstractConversationManager.java
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationImpl.java
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ServletConversationManager.java
core/trunk/impl/src/main/java/org/jboss/weld/jsf/ConversationAwareViewHandler.java
core/trunk/impl/src/main/java/org/jboss/weld/jsf/WeldPhaseListener.java
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ConversationBeanStore.java
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ConversationPropagationFilter.java
core/trunk/impl/src/main/java/org/jboss/weld/servlet/HttpPassThruSessionBeanStore.java
core/trunk/impl/src/main/java/org/jboss/weld/servlet/HttpSessionBeanStore.java
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ServletLifecycle.java
core/trunk/tests/src/test/java/org/jboss/weld/tests/serialization/SerializationTest.java
core/trunk/tests/src/test/java/org/jboss/weld/tests/serialization/TestConversationManager.java
Log:
Conversation Manager API
Integration of lifecycle and JSF to CM API
Session invalidation survival (load + save of BeanStores)
Sync + asynch conversation manager
Modified:
api/trunk/weld/src/main/java/org/jboss/weld/conversation/ConversationIdGenerator.java
===================================================================
---
api/trunk/weld/src/main/java/org/jboss/weld/conversation/ConversationIdGenerator.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
api/trunk/weld/src/main/java/org/jboss/weld/conversation/ConversationIdGenerator.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -20,7 +20,7 @@
* Generates conversation ID:s for the conversation manager
*
* @author Nicklas Karlsson
- * @see
org.jboss.weld.conversation.ConversationManager#beginOrRestoreConversation(String)
+ * @see org.jboss.weld.conversation.ConversationManager#setupConversation(String)
*/
public interface ConversationIdGenerator
{
Deleted:
api/trunk/weld/src/main/java/org/jboss/weld/conversation/ConversationManager.java
===================================================================
---
api/trunk/weld/src/main/java/org/jboss/weld/conversation/ConversationManager.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
api/trunk/weld/src/main/java/org/jboss/weld/conversation/ConversationManager.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -1,56 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2010, Red Hat, Inc., and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jboss.weld.conversation;
-
-import java.util.Set;
-
-import javax.enterprise.context.Conversation;
-
-/**
- * A conversation manager responsible for starting, resuming and ending conversations
- *
- * @author Nicklas Karlsson
- * @see org.jboss.weld.conversation.ConversationManager
- */
-public interface ConversationManager
-{
- /**
- * Begins or restores a conversation
- *
- * @param cid The incoming conversation ID. Can be null in cases of transient
conversations
- */
- public abstract void beginOrRestoreConversation(String cid);
-
- /**
- * Cleans up the current conversation, destroying transient conversation and handling
- * long-running conversations
- */
- public abstract void cleanupConversation();
-
- /**
- * Destroys all long-running conversations
- */
- public abstract void destroyAllConversations();
-
- /**
- * Gets the currently managed long-running conversations
- *
- * @return the conversations
- */
- public abstract Set<Conversation> getLongRunningConversations();
-
-}
Modified: core/trunk/impl/src/main/java/org/jboss/weld/context/ContextLifecycle.java
===================================================================
--- core/trunk/impl/src/main/java/org/jboss/weld/context/ContextLifecycle.java 2010-02-26
08:08:17 UTC (rev 5963)
+++ core/trunk/impl/src/main/java/org/jboss/weld/context/ContextLifecycle.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -35,6 +35,7 @@
import org.jboss.weld.bootstrap.api.Service;
import org.jboss.weld.context.api.BeanStore;
import org.jboss.weld.context.api.helpers.ConcurrentHashMapBeanStore;
+import org.jboss.weld.context.beanstore.HashMapBeanStore;
import org.slf4j.cal10n.LocLogger;
/**
@@ -88,6 +89,7 @@
requestContext.setBeanStore(requestBeanStore);
requestContext.setActive(true);
dependentContext.setActive(true);
+ activateConversationContext();
}
public void endRequest(String id, BeanStore requestBeanStore)
@@ -98,6 +100,7 @@
requestContext.destroy();
requestContext.setActive(false);
requestContext.setBeanStore(null);
+ deactivateConversationContext();
}
public boolean isRequestActive()
@@ -181,4 +184,16 @@
return dependentContext;
}
+ public void activateConversationContext()
+ {
+ conversationContext.setActive(true);
+ conversationContext.setBeanStore(new HashMapBeanStore());
+ }
+
+ public void deactivateConversationContext()
+ {
+ conversationContext.setActive(false);
+ conversationContext.setBeanStore(null);
+ }
+
}
Modified: core/trunk/impl/src/main/java/org/jboss/weld/context/ConversationContext.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/context/ConversationContext.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/context/ConversationContext.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -24,6 +24,8 @@
import javax.enterprise.context.ConversationScoped;
+import org.jboss.weld.context.api.BeanStore;
+
/**
* The conversation context
*
@@ -31,15 +33,29 @@
*/
public class ConversationContext extends AbstractThreadLocalMapContext
{
-
- /**
- * Constructor
- */
public ConversationContext()
{
super(ConversationScoped.class);
}
+ private void mergeBeanStores(BeanStore from, BeanStore to)
+ {
+ for (String id : from.getContextualIds())
+ {
+ to.put(id, from.get(id));
+ }
+ }
+
+ public void loadTransientBeanStore(BeanStore sourceBeanStore)
+ {
+ mergeBeanStores(sourceBeanStore, getBeanStore());
+ }
+
+ public void saveTransientBeanStore(BeanStore targetBeanStore)
+ {
+ mergeBeanStores(getBeanStore(), targetBeanStore);
+ }
+
@Override
public String toString()
{
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/context/beanstore/AbstractAttributeBackedBeanStore.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/context/beanstore/AbstractAttributeBackedBeanStore.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/context/beanstore/AbstractAttributeBackedBeanStore.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -29,7 +29,6 @@
import org.jboss.weld.context.api.BeanStore;
import org.jboss.weld.context.api.ContextualInstance;
-import org.jboss.weld.util.Names;
import org.jboss.weld.util.collections.EnumerationList;
import org.slf4j.cal10n.LocLogger;
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/context/beanstore/HashMapBeanStore.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/context/beanstore/HashMapBeanStore.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/context/beanstore/HashMapBeanStore.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -21,8 +21,6 @@
import java.util.HashMap;
import java.util.Map;
-import javax.enterprise.context.spi.Contextual;
-
import org.jboss.weld.context.api.ContextualInstance;
import org.jboss.weld.context.api.helpers.AbstractMapBackedBeanStore;
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/conversation/AbstractConversationManager.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/conversation/AbstractConversationManager.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/conversation/AbstractConversationManager.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -1,10 +1,4 @@
/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- *
- * Use is subject to license terms.
- *
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
@@ -15,7 +9,7 @@
* You may obtain a copy of the License at
*
http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
+ * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
@@ -30,14 +24,15 @@
import static
org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_TERMINATION_SCHEDULED;
import static org.jboss.weld.logging.messages.ConversationMessage.DESTROY_ALL_LRC;
import static org.jboss.weld.logging.messages.ConversationMessage.DESTROY_LRC;
-import static
org.jboss.weld.logging.messages.ConversationMessage.DESTROY_TRANSIENT_COVERSATION;
import static org.jboss.weld.logging.messages.ConversationMessage.LRC_COUNT;
import static
org.jboss.weld.logging.messages.ConversationMessage.NO_CONVERSATION_TO_RESTORE;
import static
org.jboss.weld.logging.messages.ConversationMessage.UNABLE_TO_RESTORE_CONVERSATION;
import java.io.Serializable;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@@ -45,7 +40,6 @@
import java.util.concurrent.TimeUnit;
import javax.enterprise.context.Conversation;
-import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import org.jboss.weld.Container;
@@ -65,53 +59,103 @@
*/
public abstract class AbstractConversationManager implements ConversationManager,
Serializable
{
-
- private static final long serialVersionUID = 8375026855239413267L;
+ private static final long serialVersionUID = 1L;
private static final LocLogger log = loggerFactory().getLogger(CONVERSATION);
- // The current conversation
+ private boolean asynchronous = false;
+
@Inject
- private Instance<ConversationImpl> currentConversation;
+ protected ConversationImpl conversation;
- // The conversation timeout in milliseconds waiting for access to a blocked
- // conversation
+ @Inject
+ private ConversationIdGenerator conversationIdGenerator;
+
@ConversationConcurrentAccessTimeout
private long concurrentAccessTimeout;
- // A map of current active long-running conversation entries
- private Map<String, ConversationEntry> longRunningConversations;
+ private Map<String, ManagedConversation> managedConversations;
- /**
- * Creates a new conversation manager
- */
public AbstractConversationManager()
{
- longRunningConversations = new ConcurrentHashMap<String,
ConversationEntry>();
+ managedConversations = new ConcurrentHashMap<String, ManagedConversation>();
}
- public void beginOrRestoreConversation(String cid)
+ public ConversationManager setAsynchronous(boolean asynchronous)
{
+ if (this.asynchronous == asynchronous)
+ {
+ return this;
+ }
+ if (!managedConversations.isEmpty())
+ {
+ log.warn("Switching modes with non-transient conversations present resets
the timeouts");
+ }
+ if (asynchronous)
+ {
+ switchToAsynchronous();
+ }
+ else
+ {
+ switchToNonAsynchronous();
+ }
+ return this;
+ }
+
+ private void switchToNonAsynchronous()
+ {
+ for (ManagedConversation managedConversation : managedConversations.values())
+ {
+ managedConversation.cancelTermination();
+ managedConversation.setTerminationHandle(null);
+ managedConversation.touch();
+ }
+ }
+
+ private void switchToAsynchronous()
+ {
+ for (ManagedConversation managedConversation : managedConversations.values())
+ {
+
managedConversation.setTerminationHandle(scheduleForTermination(managedConversation.getConversation()));
+ }
+ }
+
+ private void destroyExpiredConversations()
+ {
+ for (Iterator<ManagedConversation> i =
managedConversations.values().iterator(); i.hasNext();)
+ {
+ ManagedConversation managedConversation = i.next();
+ if (managedConversation.isExpired())
+ {
+ managedConversation.destroy();
+ i.remove();
+ }
+ }
+ }
+
+ public ConversationManager setupConversation(String cid)
+ {
+ if (!asynchronous)
+ {
+ destroyExpiredConversations();
+ }
if (cid == null)
{
- // No incoming conversation ID, nothing to do here, continue with
- // a transient conversation
log.trace(NO_CONVERSATION_TO_RESTORE);
- return;
+ return this;
}
- if (!longRunningConversations.containsKey(cid))
+ ManagedConversation resumedManagedConversation = managedConversations.get(cid);
+ if (resumedManagedConversation == null)
{
- // We got an incoming conversation ID but it was not in the map of
- // known ones, nothing to do. Log and return to continue with a
- // transient conversation
throw new NonexistentConversationException(UNABLE_TO_RESTORE_CONVERSATION, cid,
"id not known");
}
- ConversationEntry resumedConversationEntry = longRunningConversations.get(cid);
- // Try to get a lock to the requested conversation, log and return to
- // continue with a transient conversation if we fail
+ if (asynchronous && !resumedManagedConversation.cancelTermination())
+ {
+ throw new BusyConversationException(CONVERSATION_LOCK_UNAVAILABLE);
+ }
try
{
- if (!resumedConversationEntry.lock(concurrentAccessTimeout))
+ if (!resumedManagedConversation.lock(concurrentAccessTimeout))
{
throw new BusyConversationException(CONVERSATION_LOCK_UNAVAILABLE);
}
@@ -121,79 +165,82 @@
Thread.currentThread().interrupt();
throw new BusyConversationException(CONVERSATION_LOCK_UNAVAILABLE);
}
- // If we can't cancel the termination, release the lock, return and
- // continue
- // with a transient conversation
- if (!resumedConversationEntry.cancelTermination())
+ String oldConversation = conversation.toString();
+ conversation.switchTo(resumedManagedConversation.getConversation());
+ getConversationContext().loadTransientBeanStore(getBeanStore(cid));
+ log.trace(CONVERSATION_SWITCHED, oldConversation, conversation);
+ return this;
+ }
+
+ private ConversationContext getConversationContext()
+ {
+ return
Container.instance().services().get(ContextLifecycle.class).getConversationContext();
+ }
+
+ public ConversationManager teardownConversation()
+ {
+ log.trace(CLEANING_UP_CONVERSATION, conversation);
+ if (conversation.isTransient())
{
- resumedConversationEntry.unlock();
- throw new BusyConversationException(CONVERSATION_LOCK_UNAVAILABLE);
+ endTransientConversation();
+ if (conversation.getResumedId() != null)
+ {
+ handleResumedConversation();
+ }
}
else
{
- // If all goes well, set the identity of the current conversation to
- // match the fetched long-running one
- String oldConversation = currentConversation.toString();
- currentConversation.get().switchTo(resumedConversationEntry.getConversation());
- log.trace(CONVERSATION_SWITCHED, oldConversation, currentConversation);
+ endNonTransientConversation();
}
+ return this;
}
- // TODO: check that stuff gets terminated when you flip between several
- // long-running conversations
- public void cleanupConversation()
+ private void handleResumedConversation()
{
- log.trace(CLEANING_UP_CONVERSATION, currentConversation);
- String cid = currentConversation.get().getUnderlyingId();
- if (!currentConversation.get().isTransient())
+ ManagedConversation resumedConversation =
managedConversations.remove(conversation.getResumedId());
+ if (resumedConversation == null)
{
- Future<?> terminationHandle = scheduleForTermination(cid,
currentConversation.get().getTimeout());
- // When the conversation ends, a long-running conversation needs to
- // start its self-destruct. We can have the case where the conversation
- // is a previously known conversation (that had it's termination
- // canceled in the
- // beginConversation) or the case where we have a completely new
- // long-running conversation.
- ConversationEntry longRunningConversation = longRunningConversations.get(cid);
- if (longRunningConversation != null)
+ return;
+ }
+ resumedConversation.unlock();
+ resumedConversation.destroy();
+ }
+
+ private void endNonTransientConversation()
+ {
+
getConversationContext().saveTransientBeanStore(getBeanStore(conversation.getId()));
+ ManagedConversation oldManagedConversation =
managedConversations.get(conversation.getId());
+ if (oldManagedConversation != null)
+ {
+ oldManagedConversation.unlock();
+ if (asynchronous)
{
- longRunningConversation.unlock();
- longRunningConversation.reScheduleTermination(terminationHandle);
+
oldManagedConversation.setTerminationHandle(scheduleForTermination(conversation));
}
else
{
- ConversationEntry conversationEntry = ConversationEntry.of(getBeanStore(cid),
currentConversation.get(), terminationHandle);
- longRunningConversations.put(cid, conversationEntry);
+ oldManagedConversation.touch();
}
- log.trace(CONVERSATION_TERMINATION_SCHEDULED, currentConversation);
- log.trace(LRC_COUNT, longRunningConversations.size());
}
else
{
- // If the conversation is not long-running it can be a transient
- // conversation that has been so from the start or it can be a
- // long-running conversation that has been demoted during the request
- log.trace(DESTROY_TRANSIENT_COVERSATION, currentConversation);
- ConversationEntry longRunningConversation =
longRunningConversations.remove(cid);
- if (longRunningConversation != null)
+ ManagedConversation newManagedConversation =
ManagedConversation.of(conversation.unProxy(this), getBeanStore(conversation.getId()));
+ if (asynchronous)
{
- longRunningConversation.cancelTermination();
- longRunningConversation.unlock();
+ log.trace(CONVERSATION_TERMINATION_SCHEDULED, conversation);
+
newManagedConversation.setTerminationHandle(scheduleForTermination(conversation));
}
- ConversationContext conversationContext =
Container.instance().services().get(ContextLifecycle.class).getConversationContext();
- conversationContext.destroy();
+ managedConversations.put(conversation.getId(), newManagedConversation);
}
- // If the conversation has been switched from one long
- // running-conversation to another with
- // Conversation.begin(String), we need to unlock the original conversation
- // and re-schedule
- // it for termination
- String originalCid = currentConversation.get().getOriginalId();
- ConversationEntry longRunningConversation = originalCid == null ? null :
longRunningConversations.get(originalCid);
- if (longRunningConversation != null)
+ log.trace(LRC_COUNT, managedConversations.size());
+ }
+
+ private void endTransientConversation()
+ {
+ getConversationContext().destroy();
+ if (conversation.getResumedId() != null)
{
- longRunningConversation.unlock();
-
longRunningConversation.reScheduleTermination(scheduleForTermination(originalCid,
currentConversation.get().getTimeout()));
+ getBeanStore(conversation.getResumedId()).clear();
}
}
@@ -203,66 +250,88 @@
* @param cid The id of the conversation to terminate
* @return The asynchronous job handle
*/
- private Future<?> scheduleForTermination(String cid, long timeout)
+ private Future<?> scheduleForTermination(Conversation conversation)
{
- Runnable terminationTask = new TerminationTask(cid);
- return
Container.instance().services().get(ScheduledExecutorServiceFactory.class).get().schedule(terminationTask,
timeout, TimeUnit.MILLISECONDS);
+ Runnable terminationTask = new TerminationTask(conversation.getId());
+ return
Container.instance().services().get(ScheduledExecutorServiceFactory.class).get().schedule(terminationTask,
conversation.getTimeout(), TimeUnit.MILLISECONDS);
}
- /**
- * A termination task that destroys the conversation entry
- *
- * @author Nicklas Karlsson
- *
- */
private class TerminationTask implements Runnable
{
- // The conversation ID to terminate
private String cid;
- /**
- * Creates a new termination task
- *
- * @param cid The conversation ID
- */
public TerminationTask(String cid)
{
this.cid = cid;
}
- /**
- * Executes the termination
- */
public void run()
{
log.debug(DESTROY_LRC, cid, "conversation timed out");
- longRunningConversations.remove(cid).destroy();
- log.trace(LRC_COUNT, longRunningConversations.size());
+ ManagedConversation managedConversation = managedConversations.remove(cid);
+ if (managedConversation != null)
+ {
+ managedConversation.destroy();
+ }
+ log.trace(LRC_COUNT, managedConversations.size());
}
}
- public void destroyAllConversations()
+ public ConversationManager destroyAllConversations()
{
log.debug(DESTROY_ALL_LRC, "session ended");
- log.trace(LRC_COUNT, longRunningConversations.size());
- for (ConversationEntry conversationEntry : longRunningConversations.values())
+ log.trace(LRC_COUNT, managedConversations.size());
+ for (ManagedConversation managedConversation : managedConversations.values())
{
- log.debug(DESTROY_LRC, conversationEntry, "session ended");
- conversationEntry.destroy();
+ log.debug(DESTROY_LRC, managedConversation, "session ended");
+ managedConversation.destroy();
}
- longRunningConversations.clear();
+ managedConversations.clear();
+ return this;
}
public Set<Conversation> getLongRunningConversations()
{
Set<Conversation> conversations = new HashSet<Conversation>();
- for (ConversationEntry conversationEntry : longRunningConversations.values())
+ for (ManagedConversation managedConversation : managedConversations.values())
{
- conversations.add(conversationEntry.getConversation());
+ conversations.add(managedConversation.getConversation());
}
return Collections.unmodifiableSet(conversations);
}
-
- public abstract BeanStore getBeanStore(String cid);
+ public ConversationManager activateContext()
+ {
+
Container.instance().services().get(ContextLifecycle.class).activateConversationContext();
+ return this;
+ }
+
+ public ConversationManager deactivateContext()
+ {
+
Container.instance().services().get(ContextLifecycle.class).deactivateConversationContext();
+ return this;
+ }
+
+ public String generateConversationId()
+ {
+ return conversationIdGenerator.nextId();
+ }
+
+ public Map<String, Conversation> getConversations()
+ {
+ Map<String, Conversation> conversations = new HashMap<String,
Conversation>();
+ for (ManagedConversation entry : managedConversations.values())
+ {
+ conversations.put(entry.getConversation().getId(), entry.getConversation());
+ }
+ return Collections.unmodifiableMap(conversations);
+ }
+
+ public boolean isContextActive()
+ {
+ return getConversationContext().isActive();
+ }
+
+ protected abstract BeanStore getBeanStore(String cid);
+
}
Deleted: core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationEntry.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationEntry.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationEntry.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -1,176 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, Red Hat, Inc., and individual contributors
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jboss.weld.conversation;
-
-import static org.jboss.weld.logging.Category.CONVERSATION;
-import static org.jboss.weld.logging.LoggerFactory.loggerFactory;
-import static org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_LOCKED;
-import static
org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_TERMINATION_CANCELLATION_FAILED;
-import static
org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_TERMINATION_CANCELLED;
-import static
org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_UNAVAILBLE;
-import static org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_UNLOCKED;
-import static
org.jboss.weld.logging.messages.ConversationMessage.ILLEGAL_CONVERSATION_UNLOCK_ATTEMPT;
-
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
-
-import org.jboss.weld.context.ConversationContext;
-import org.jboss.weld.context.api.BeanStore;
-import org.slf4j.cal10n.LocLogger;
-
-/**
- * Represents a long-running conversation entry
- *
- * @author Nicklas Karlsson
- */
-public class ConversationEntry
-{
- private static final LocLogger log = loggerFactory().getLogger(CONVERSATION);
-
- // The conversation
- private ConversationImpl conversation;
- // The handle to the asynchronous timeout task
- private Future<?> terminationHandle;
- // The lock for concurrent access prevention
- private ReentrantLock concurrencyLock;
- // The Bean Store of the conversations
- private BeanStore beanStore;
-
- /**
- * Creates a new conversation entry
- *
- * @param cid The conversation ID
- * @param terminationHandle The timeout termination handle
- */
- protected ConversationEntry(BeanStore beanStore, ConversationImpl conversation,
Future<?> terminationHandle)
- {
- this.beanStore = beanStore;
- // conversation is a proxy so we need to make a "real" instance
- this.conversation = new ConversationImpl(conversation);
- this.terminationHandle = terminationHandle;
- this.concurrencyLock = new ReentrantLock();
- }
-
- /**
- * Factory method
- *
- * @param cid The conversation ID
- * @param terminationHandle The timeout termination handle
- * @return A new conversation entry
- */
- public static ConversationEntry of(BeanStore beanStore, ConversationImpl conversation,
Future<?> terminationHandle)
- {
- return new ConversationEntry(beanStore, conversation, terminationHandle);
- }
-
- /**
- * Cancels the timeout termination
- *
- * @return True if successful, false otherwise
- */
- public boolean cancelTermination()
- {
- if (terminationHandle.isCancelled())
- {
- return true;
- }
- boolean success = terminationHandle.cancel(false);
- if (success)
- {
- log.trace(CONVERSATION_TERMINATION_CANCELLED, conversation);
- }
- else
- {
- log.warn(CONVERSATION_TERMINATION_CANCELLATION_FAILED, conversation);
- }
- return success;
- }
-
- /**
- * Destroys the conversation and it's associated conversational context
- */
- public void destroy()
- {
- if (!terminationHandle.isCancelled())
- {
- cancelTermination();
- }
- ConversationContext terminationContext = new ConversationContext();
- terminationContext.setBeanStore(beanStore);
- terminationContext.destroy();
- }
-
- /**
- * Attempts to lock the conversation for exclusive usage
- *
- * @param timeout The time in milliseconds to wait on the lock
- * @return True if lock was successful, false otherwise
- * @throws InterruptedException If the lock operation was unsuccessful
- */
- public boolean lock(long timeout) throws InterruptedException
- {
- boolean success = concurrencyLock.tryLock(timeout, TimeUnit.MILLISECONDS);
- if (success)
- {
- log.trace(CONVERSATION_LOCKED, conversation);
- }
- else
- {
- log.warn(CONVERSATION_UNAVAILBLE, timeout, conversation);
- }
- return success;
- }
-
- /**
- * Attempts to unlock the conversation
- *
- * @return true if the unlock was successful, false otherwise
- */
- public boolean unlock()
- {
- if (!concurrencyLock.isLocked())
- {
- return true;
- }
- if (concurrencyLock.isHeldByCurrentThread())
- {
- concurrencyLock.unlock();
- log.trace(CONVERSATION_UNLOCKED, conversation);
- }
- else
- {
- log.warn(ILLEGAL_CONVERSATION_UNLOCK_ATTEMPT, conversation, "not
owner");
- }
- return !concurrencyLock.isLocked();
- }
-
- /**
- * Re-schedules timeout termination
- *
- * @param terminationHandle The fresh timeout termination handle
- */
- public void reScheduleTermination(Future<?> terminationHandle)
- {
- this.terminationHandle = terminationHandle;
- }
-
- public ConversationImpl getConversation()
- {
- return conversation;
- }
-}
Modified: core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationImpl.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationImpl.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationImpl.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -18,7 +18,6 @@
import static org.jboss.weld.logging.Category.CONVERSATION;
import static org.jboss.weld.logging.LoggerFactory.loggerFactory;
-import static org.jboss.weld.logging.messages.BeanManagerMessage.CONTEXT_NOT_ACTIVE;
import static
org.jboss.weld.logging.messages.ConversationMessage.BEGIN_CALLED_ON_LONG_RUNNING_CONVERSATION;
import static org.jboss.weld.logging.messages.ConversationMessage.DEMOTED_LRC;
import static
org.jboss.weld.logging.messages.ConversationMessage.END_CALLED_ON_TRANSIENT_CONVERSATION;
@@ -27,15 +26,13 @@
import java.io.Serializable;
+import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Default;
import javax.inject.Inject;
import javax.inject.Named;
-import org.jboss.weld.Container;
-import org.jboss.weld.context.ContextLifecycle;
-import org.jboss.weld.context.ContextNotActiveException;
import org.jboss.weld.exceptions.ForbiddenStateException;
import org.slf4j.cal10n.LocLogger;
@@ -50,33 +47,30 @@
@Default
public class ConversationImpl implements Conversation, Serializable
{
+ private static final long serialVersionUID = 1L;
- /**
- * Eclipse generated UID.
- */
- private static final long serialVersionUID = 5262382965141841363L;
-
private static final LocLogger log = loggerFactory().getLogger(CONVERSATION);
- // The conversation ID
+ @Inject
+ private ConversationManager conversationManager;
+
private String id;
- // The original conversation ID (if any)
- private String originalId;
- // Is the conversation long-running?
private boolean _transient = true;
- // The timeout in milliseconds
private long timeout;
+ private String resumedId;
/**
* Creates a new conversation
*/
- public ConversationImpl() {}
-
- protected void checkConversationActive()
+ public ConversationImpl()
{
- if
(!Container.instance().services().get(ContextLifecycle.class).getConversationContext().isActive())
+ }
+
+ private void checkForActiveConversationContext(String when)
+ {
+ if (!conversationManager.isContextActive())
{
- throw new ContextNotActiveException(CONTEXT_NOT_ACTIVE,
"@ConversationScoped");
+ throw new ContextNotActiveException("Conversation context not active when
calling " + when + " on " + this);
}
}
@@ -85,12 +79,19 @@
*
* @param conversation The old conversation
*/
- public ConversationImpl(ConversationImpl conversation)
+ protected ConversationImpl(Conversation conversation, ConversationManager
conversationManager)
{
- this.id = conversation.getUnderlyingId();
- this._transient = conversation.isTransient();
- this.timeout = conversation.getTimeout();
+ id = conversation.getId();
+ _transient = conversation.isTransient();
+ timeout = conversation.getTimeout();
+ // manual injection because of new() usage for unProxy();
+ this.conversationManager = conversationManager;
}
+
+ public static ConversationImpl of(Conversation conversation, ConversationManager
conversationManager)
+ {
+ return new ConversationImpl(conversation, conversationManager);
+ }
/**
* Initializes a new conversation
@@ -99,83 +100,66 @@
* @param timeout The conversation inactivity timeout
*/
@Inject
- public void init(ConversationIdGenerator conversationIdGenerator,
@ConversationInactivityTimeout long timeout)
+ public void init(@ConversationInactivityTimeout long timeout)
{
- this.id = conversationIdGenerator.nextId();
this.timeout = timeout;
- this._transient = true;
+ _transient = true;
}
public void begin()
{
- checkConversationActive();
- if (!isTransient())
+ checkForActiveConversationContext("Conversation.begin()");
+ if (!_transient)
{
throw new ForbiddenStateException(BEGIN_CALLED_ON_LONG_RUNNING_CONVERSATION);
}
log.debug(PROMOTED_TRANSIENT, id);
- this._transient = false;
+ _transient = false;
+ id = conversationManager.generateConversationId();
}
public void begin(String id)
{
- checkConversationActive();
- // Store away the (first) change to the conversation ID. If the original
- // conversation was long-running,
- // we might have to place it back for termination once the request is
- // over.
- if (originalId == null)
+ checkForActiveConversationContext("Conversation.begin(String)");
+ if (!_transient)
{
- originalId = id;
+ throw new ForbiddenStateException(BEGIN_CALLED_ON_LONG_RUNNING_CONVERSATION);
}
+ if (conversationManager.getConversations().containsKey(id))
+ {
+ throw new IllegalStateException("Conversation ID " + id + " is
already in use");
+ }
+ _transient = false;
this.id = id;
- begin();
}
public void end()
{
- checkConversationActive();
- if (isTransient())
+ checkForActiveConversationContext("Conversation.end()");
+ if (_transient)
{
throw new ForbiddenStateException(END_CALLED_ON_TRANSIENT_CONVERSATION);
}
log.debug(DEMOTED_LRC, id);
- this._transient = true;
+ _transient = true;
+ id = null;
}
public String getId()
{
- checkConversationActive();
- if (!isTransient())
- {
- return id;
- }
- else
- {
- return null;
- }
- }
-
- /**
- * Get the Conversation Id, regardless of whether the conversation is long
- * running or transient, needed for internal operations
- *
- * @return the id
- */
- public String getUnderlyingId()
- {
+ checkForActiveConversationContext("Conversation.getId()");
return id;
}
public long getTimeout()
{
- checkConversationActive();
+ checkForActiveConversationContext("Conversation.getTimeout()");
return timeout;
}
public void setTimeout(long timeout)
{
- checkConversationActive();
+ checkForActiveConversationContext("Conversation.setTimeout()");
this.timeout = timeout;
}
@@ -185,37 +169,28 @@
* @param conversation The new conversation
*
*/
- public void switchTo(ConversationImpl conversation)
+ public void switchTo(Conversation conversation)
{
log.debug(SWITCHED_CONVERSATION, this, conversation);
- id = conversation.id;
- this._transient = conversation._transient;
- timeout = conversation.timeout;
+ id = conversation.getId();
+ _transient = conversation.isTransient();
+ timeout = conversation.getTimeout();
+ this.resumedId = id;
}
@Override
public String toString()
{
- return "ID: " + id + ", transient: " + isTransient() + ",
timeout: " + timeout + "ms";
+ return "ID: " + id + ", transient: " + _transient + ",
timeout: " + timeout + "ms";
}
- /**
- * Gets the original ID of the conversation
- *
- * @return The id
- */
- public String getOriginalId()
- {
- return originalId;
- }
-
@Override
public boolean equals(Object obj)
{
if (obj instanceof ConversationImpl)
{
ConversationImpl that = (ConversationImpl) obj;
- return (id == null || that.getUnderlyingId() == null) ? false :
id.equals(that.getUnderlyingId());
+ return (id == null || that.getId() == null) ? false : id.equals(that.getId());
}
else
{
@@ -231,9 +206,22 @@
public boolean isTransient()
{
- checkConversationActive();
+ checkForActiveConversationContext("Conversation.isTransient()");
return _transient;
}
-
-
+
+ public void setId(String id)
+ {
+ this.id = id;
+ }
+
+ public String getResumedId()
+ {
+ return resumedId;
+ }
+
+ public ConversationImpl unProxy(ConversationManager conversationManager)
+ {
+ return new ConversationImpl(this, conversationManager);
+ }
}
Added: core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationManager.java
===================================================================
--- core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationManager.java
(rev 0)
+++
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ConversationManager.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -0,0 +1,96 @@
+package org.jboss.weld.conversation;
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.util.Map;
+
+import javax.enterprise.context.Conversation;
+
+public interface ConversationManager
+{
+ /**
+ * Checks the state of the conversation context
+ *
+ * @return true if the conversation context is active, false otherwise
+ */
+ public abstract boolean isContextActive();
+
+ /**
+ * Activates the conversation context
+ *
+ * @return The conversation manager
+ *
+ * @throws IllegalStateException if the context is already active
+ */
+ public abstract ConversationManager activateContext();
+
+ /**
+ * Deactivates the conversation context
+ *
+ * @return The conversation manager
+ *
+ * @throws IllegalStateException if the context is already deactive
+ */
+ public abstract ConversationManager deactivateContext();
+
+ /**
+ * Resumes a long running conversation. If the cid is null, nothing is done and the
current
+ * transient conversation is resumed
+ *
+ *
+ * @param cid The conversation id to restore
+ * @return The conversation manager
+ * @throws NonexistentConversationException If the non-transient conversation is not
known
+ * @throws BusyConversationException If the conversation is locked and not released
while waiting
+ * @throws IllegalStateException if the conversation context is not active
+ */
+
+ public abstract ConversationManager setupConversation(String cid);
+
+ /**
+ * Destroys the current conversation if it's transient. Stores it for conversation
+ * propagation if it's non-transient
+ *
+ * @return The conversation manager
+ * @throws IllegalStateException if the conversation context is not active
+ */
+ public abstract ConversationManager teardownConversation();
+
+ /**
+ * Gets the current non-transient conversations
+ *
+ * @return The conversations, mapped by id
+ * @throws IllegalStateException if the conversation context is not active
+ */
+ public abstract Map<String, Conversation> getConversations();
+
+ /**
+ * Returns a new, session-unique conversation ID
+ *
+ * @return The conversation id
+ * @throws IllegalStateException if the conversation context is not active
+ */
+ public abstract String generateConversationId();
+
+ /**
+ * Destroys all non-transient conversations
+ *
+ * @return The conversation manager
+ */
+ public abstract ConversationManager destroyAllConversations();
+
+}
Added: core/trunk/impl/src/main/java/org/jboss/weld/conversation/ManagedConversation.java
===================================================================
--- core/trunk/impl/src/main/java/org/jboss/weld/conversation/ManagedConversation.java
(rev 0)
+++
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ManagedConversation.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -0,0 +1,217 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat, Inc., and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jboss.weld.conversation;
+
+import static org.jboss.weld.logging.Category.CONVERSATION;
+import static org.jboss.weld.logging.LoggerFactory.loggerFactory;
+import static org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_LOCKED;
+import static
org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_TERMINATION_CANCELLATION_FAILED;
+import static
org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_TERMINATION_CANCELLED;
+import static
org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_UNAVAILBLE;
+import static org.jboss.weld.logging.messages.ConversationMessage.CONVERSATION_UNLOCKED;
+import static
org.jboss.weld.logging.messages.ConversationMessage.ILLEGAL_CONVERSATION_UNLOCK_ATTEMPT;
+
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+import org.jboss.weld.context.ConversationContext;
+import org.jboss.weld.context.api.BeanStore;
+import org.slf4j.cal10n.LocLogger;
+
+/**
+ * Represents a long-running conversation entry
+ *
+ * @author Nicklas Karlsson
+ */
+public class ManagedConversation
+{
+ private static final LocLogger log = loggerFactory().getLogger(CONVERSATION);
+
+ private ConversationImpl conversation;
+ private Future<?> terminationHandle;
+ private ReentrantLock concurrencyLock;
+ private BeanStore beanStore;
+ private long touched;
+
+ /**
+ * Creates a new conversation entry
+ *
+ * @param cid The conversation ID
+ * @param terminationHandle The timeout termination handle
+ */
+ protected ManagedConversation(ConversationImpl conversation, BeanStore beanStore,
Future<?> terminationHandle)
+ {
+ this.conversation = conversation;
+ this.beanStore = beanStore;
+ this.terminationHandle = terminationHandle;
+ this.concurrencyLock = new ReentrantLock();
+ touch();
+ }
+
+ /**
+ * Static factory method
+ *
+ * @param conversation The conversation to manager
+ * @param beanStore The beanstore of the conversation for termination
+ * @param terminationHandle The asynchronous termination handle
+ *
+ * @return A manager conversation
+ */
+ public static ManagedConversation of(ConversationImpl conversation, BeanStore
beanStore, Future<?> terminationHandle)
+ {
+ return new ManagedConversation(conversation, beanStore, terminationHandle);
+ }
+
+ /**
+ * Static factory method
+ *
+ * @param conversation The conversation to manager
+ * @param beanStore The beanstore of the conversation for termination
+ *
+ * @return A manager conversation
+ */
+ public static ManagedConversation of(ConversationImpl conversation, BeanStore
beanStore)
+ {
+ return of(conversation, beanStore, null);
+ }
+
+ /**
+ * Cancels the asynchronous termination
+ *
+ * @return True if successful, false otherwise
+ */
+ public boolean cancelTermination()
+ {
+ if (terminationHandle == null)
+ {
+ return false;
+ }
+ if (terminationHandle.isCancelled())
+ {
+ return true;
+ }
+ boolean success = terminationHandle.cancel(false);
+ if (success)
+ {
+ log.trace(CONVERSATION_TERMINATION_CANCELLED, conversation);
+ }
+ else
+ {
+ log.warn(CONVERSATION_TERMINATION_CANCELLATION_FAILED, conversation);
+ }
+ return success;
+ }
+
+ /**
+ * Destroys the conversation and it's associated conversational context
+ */
+ public void destroy()
+ {
+ // FIXME: Not really needed but there is a small window for overlapping if it
fires(?)
+ if (terminationHandle != null && !terminationHandle.isCancelled())
+ {
+ cancelTermination();
+ }
+ ConversationContext terminationContext = new ConversationContext();
+ terminationContext.setBeanStore(beanStore);
+ terminationContext.destroy();
+ }
+
+ /**
+ * Attempts to lock the conversation for exclusive usage
+ *
+ * @param timeout The time in milliseconds to wait on the lock
+ * @return True if lock was successful, false otherwise
+ * @throws InterruptedException If the lock operation was unsuccessful
+ */
+ public boolean lock(long timeout) throws InterruptedException
+ {
+ boolean success = concurrencyLock.tryLock(timeout, TimeUnit.MILLISECONDS);
+ if (success)
+ {
+ log.trace(CONVERSATION_LOCKED, conversation);
+ }
+ else
+ {
+ log.warn(CONVERSATION_UNAVAILBLE, timeout, conversation);
+ }
+ return success;
+ }
+
+ /**
+ * Attempts to unlock the conversation
+ *
+ * @return true if the unlock was successful, false otherwise
+ */
+ public boolean unlock()
+ {
+ if (!concurrencyLock.isLocked())
+ {
+ return true;
+ }
+ if (concurrencyLock.isHeldByCurrentThread())
+ {
+ concurrencyLock.unlock();
+ log.trace(CONVERSATION_UNLOCKED, conversation);
+ }
+ else
+ {
+ log.warn(ILLEGAL_CONVERSATION_UNLOCK_ATTEMPT, conversation, "not
owner");
+ }
+ return !concurrencyLock.isLocked();
+ }
+
+ /**
+ * Sets the asynchronous termination handle
+ *
+ * @param terminationHandle The termination handle
+ */
+ public void setTerminationHandle(Future<?> terminationHandle)
+ {
+ this.terminationHandle = terminationHandle;
+ }
+
+ /**
+ * Gets the wrapped conversation
+ *
+ * @return The conversation
+ */
+ public ConversationImpl getConversation()
+ {
+ return conversation;
+ }
+
+ /**
+ * Checks if the conversation has expired
+ *
+ * @return true if expired, false otherwise
+ */
+ public boolean isExpired()
+ {
+ return System.currentTimeMillis() > (touched + conversation.getTimeout());
+ }
+
+ /**
+ * Touches the managed conversation, updating the "last used" timestamp
+ */
+ public void touch()
+ {
+ touched = System.currentTimeMillis();
+ }
+
+}
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ServletConversationManager.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ServletConversationManager.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/conversation/ServletConversationManager.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -1,10 +1,4 @@
/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- *
- * Use is subject to license terms.
- *
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
@@ -15,15 +9,16 @@
* You may obtain a copy of the License at
*
http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
+ * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.weld.conversation;
+import java.io.Serializable;
+
import javax.enterprise.context.SessionScoped;
-import javax.enterprise.inject.Instance;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.servlet.http.HttpSession;
@@ -31,30 +26,19 @@
import org.jboss.weld.context.api.BeanStore;
import org.jboss.weld.servlet.ConversationBeanStore;
-/**
- * The HTTP session based conversation manager
- *
- * @author Nicklas Karlsson
- *
- */
@SessionScoped
-public class ServletConversationManager extends AbstractConversationManager
+public class ServletConversationManager extends AbstractConversationManager implements
Serializable
{
- private static final long serialVersionUID = 1647848566880659085L;
+ private static final long serialVersionUID = 1L;
private static final long CONVERSATION_TIMEOUT_IN_MS = 10 * 60 * 1000;
private static final long CONVERSATION_CONCURRENT_ACCESS_TIMEOUT_IN_MS = 1 * 1000;
private static final String CONVERSATION_ID_NAME = "cid";
- @Inject
- private Instance<HttpSession> httpSession;
- private boolean sessionInvalidated = false;
+ private boolean sessionInvalidated;
- @Override
- public BeanStore getBeanStore(String cid)
- {
- return new ConversationBeanStore(httpSession.get(), sessionInvalidated, cid);
- }
+ @Inject
+ private HttpSession httpSession;
@Produces
@ConversationInactivityTimeout
@@ -75,10 +59,17 @@
public static String getConversationIdName()
{
return CONVERSATION_ID_NAME;
- }
+ }
+ @Override
+ protected BeanStore getBeanStore(String cid)
+ {
+ return ConversationBeanStore.of(httpSession, sessionInvalidated, cid);
+ }
+
public void invalidateSession()
{
sessionInvalidated = true;
}
+
}
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/jsf/ConversationAwareViewHandler.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/jsf/ConversationAwareViewHandler.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/jsf/ConversationAwareViewHandler.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -71,7 +71,7 @@
ConversationImpl conversation = conversation(getServletContext(context));
if (!conversation.isTransient())
{
- return new FacesUrlTransformer(actionUrl,
context).appendConversationIdIfNecessary(conversation.getUnderlyingId()).getUrl();
+ return new FacesUrlTransformer(actionUrl,
context).appendConversationIdIfNecessary(conversation.getId()).getUrl();
}
else
{
Modified: core/trunk/impl/src/main/java/org/jboss/weld/jsf/WeldPhaseListener.java
===================================================================
--- core/trunk/impl/src/main/java/org/jboss/weld/jsf/WeldPhaseListener.java 2010-02-26
08:08:17 UTC (rev 5963)
+++ core/trunk/impl/src/main/java/org/jboss/weld/jsf/WeldPhaseListener.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -23,42 +23,32 @@
package org.jboss.weld.jsf;
import static org.jboss.weld.jsf.JsfHelper.getConversationId;
-import static org.jboss.weld.jsf.JsfHelper.getHttpSession;
import static org.jboss.weld.jsf.JsfHelper.getServletContext;
import static org.jboss.weld.logging.Category.JSF;
import static org.jboss.weld.logging.LoggerFactory.loggerFactory;
import static org.jboss.weld.logging.messages.JsfMessage.CLEANING_UP_CONVERSATION;
import static org.jboss.weld.logging.messages.JsfMessage.INITIATING_CONVERSATION;
-import static
org.jboss.weld.logging.messages.JsfMessage.SKIPPING_CLEANING_UP_CONVERSATION;
-import static org.jboss.weld.servlet.BeanProvider.conversation;
import static org.jboss.weld.servlet.BeanProvider.conversationManager;
-import static org.jboss.weld.servlet.BeanProvider.httpSessionManager;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpSession;
-import org.jboss.weld.Container;
-import org.jboss.weld.context.ContextLifecycle;
-import org.jboss.weld.context.ConversationContext;
-import org.jboss.weld.context.SessionContext;
-import org.jboss.weld.conversation.AbstractConversationManager;
+import org.jboss.weld.conversation.ConversationManager;
import org.slf4j.cal10n.LocLogger;
/**
* <p>
- * A JSF phase listener that initializes aspects of Weld in a more
- * fine-grained, integrated manner than what is possible with a servlet filter.
- * This phase listener works in conjunction with other hooks and callbacks
- * registered with the JSF runtime to help manage the Weld lifecycle.
+ * A JSF phase listener that initializes aspects of Weld in a more fine-grained,
+ * integrated manner than what is possible with a servlet filter. This phase
+ * listener works in conjunction with other hooks and callbacks registered with
+ * the JSF runtime to help manage the Weld lifecycle.
* </p>
*
* <p>
* It's expected that over time, this phase listener may take on more work, but
- * for now the work is focused soley on conversation management. The phase
+ * for now the work is focused solely on conversation management. The phase
* listener restores the long-running conversation if the conversation id token
* is detected in the request, activates the conversation context in either case
* (long-running or transient), and finally passivates the conversation after
@@ -70,13 +60,26 @@
*/
public class WeldPhaseListener implements PhaseListener
{
+ private static final long serialVersionUID = 1L;
+
private static final LocLogger log = loggerFactory().getLogger(JSF);
+ private ConversationManager conversationManager;
+
+ private ConversationManager getConversationManager()
+ {
+ if (conversationManager == null)
+ {
+ conversationManager =
conversationManager(getServletContext(FacesContext.getCurrentInstance()));
+ }
+ return conversationManager;
+ }
+
/**
- * Execute before every phase in the JSF life cycle. The order this
- * phase listener executes in relation to other phase listeners is
- * determined by the ordering of the faces-config.xml descriptors.
- * This phase listener should take precedence over extensions.
+ * Execute before every phase in the JSF life cycle. The order this phase
+ * listener executes in relation to other phase listeners is determined by
+ * the ordering of the faces-config.xml descriptors. This phase listener
+ * should take precedence over extensions.
*
* @param phaseEvent The phase event
*/
@@ -89,10 +92,10 @@
}
/**
- * Execute after every phase in the JSF life cycle. The order this
- * phase listener executes in relation to other phase listeners is
- * determined by the ordering of the faces-config.xml descriptors.
- * This phase listener should take precedence over extensions.
+ * Execute after every phase in the JSF life cycle. The order this phase
+ * listener executes in relation to other phase listeners is determined by
+ * the ordering of the faces-config.xml descriptors. This phase listener
+ * should take precedence over extensions.
*
* @param phaseEvent The phase event
*/
@@ -117,24 +120,14 @@
log.trace(INITIATING_CONVERSATION, "Restore View");
initiateSessionAndConversation(facesContext);
}
-
+
/**
* Execute after the Render Response phase.
*/
private void afterRenderResponse(FacesContext facesContext)
{
- SessionContext sessionContext =
Container.instance().services().get(ContextLifecycle.class).getSessionContext();
- ConversationContext conversationContext =
Container.instance().services().get(ContextLifecycle.class).getConversationContext();
- if (sessionContext.isActive())
- {
- log.trace(CLEANING_UP_CONVERSATION, "Render Response", "response
complete");
- conversationManager(getServletContext(facesContext)).cleanupConversation();
- conversationContext.setActive(false);
- }
- else
- {
- log.trace(SKIPPING_CLEANING_UP_CONVERSATION, "Render Response",
"session has been terminated");
- }
+ log.trace(CLEANING_UP_CONVERSATION, "Render Response", "response
complete");
+ getConversationManager().teardownConversation();
}
/**
@@ -142,16 +135,8 @@
*/
private void afterResponseComplete(FacesContext facesContext, PhaseId phaseId)
{
- SessionContext sessionContext =
Container.instance().services().get(ContextLifecycle.class).getSessionContext();
- if (sessionContext.isActive())
- {
- log.trace(CLEANING_UP_CONVERSATION, phaseId, "the response has been marked
complete");
- conversationManager(getServletContext(facesContext)).cleanupConversation();
- }
- else
- {
- log.trace(SKIPPING_CLEANING_UP_CONVERSATION, phaseId, "session has been
terminated");
- }
+ log.trace(CLEANING_UP_CONVERSATION, phaseId, "the response has been marked
complete");
+ getConversationManager().teardownConversation();
}
/**
@@ -162,22 +147,7 @@
*/
private void initiateSessionAndConversation(FacesContext facesContext)
{
- ServletContext servletContext = getServletContext(facesContext);
- AbstractConversationManager conversationManager = (AbstractConversationManager)
conversationManager(servletContext);
- HttpSession session = getHttpSession(facesContext);
- httpSessionManager(servletContext).setSession(session);
- try
- {
-
conversationManager.beginOrRestoreConversation(getConversationId(facesContext));
- }
- finally
- {
- String cid = conversation(servletContext).getUnderlyingId();
-
- ConversationContext conversationContext =
Container.instance().services().get(ContextLifecycle.class).getConversationContext();
- conversationContext.setBeanStore(conversationManager.getBeanStore(cid));
- conversationContext.setActive(true);
- }
+ getConversationManager().setupConversation(getConversationId(facesContext));
}
/**
Modified: core/trunk/impl/src/main/java/org/jboss/weld/servlet/ConversationBeanStore.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ConversationBeanStore.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ConversationBeanStore.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -19,6 +19,7 @@
import javax.servlet.http.HttpSession;
import org.jboss.weld.context.ConversationContext;
+import org.jboss.weld.context.api.BeanStore;
import org.jboss.weld.context.beanstore.NamingScheme;
/**
@@ -28,10 +29,9 @@
*/
public class ConversationBeanStore extends HttpPassThruSessionBeanStore
{
-
private final NamingScheme namingScheme;
- public ConversationBeanStore(HttpSession session, boolean sessionInvalidated, String
cid)
+ protected ConversationBeanStore(HttpSession session, boolean sessionInvalidated,
String cid)
{
this.namingScheme = new NamingScheme(ConversationContext.class.getName() +
"[" + cid + "]", "#");
if (sessionInvalidated)
@@ -47,4 +47,14 @@
return namingScheme;
}
+ public static BeanStore of(HttpSession httpSession, boolean sessionInvalidated, String
cid)
+ {
+ return new ConversationBeanStore(httpSession, sessionInvalidated, cid);
+ }
+
+ public static BeanStore of(HttpSession httpSession, String cid)
+ {
+ return new ConversationBeanStore(httpSession, false, cid);
+ }
+
}
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ConversationPropagationFilter.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ConversationPropagationFilter.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/servlet/ConversationPropagationFilter.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -84,8 +84,8 @@
ConversationImpl conversation = conversation(ctx);
if (!conversation.isTransient())
{
- path = new FacesUrlTransformer(path,
FacesContext.getCurrentInstance()).toRedirectViewId().toActionUrl().appendConversationIdIfNecessary(conversation.getUnderlyingId()).encode();
- conversationManager(ctx).cleanupConversation();
+ path = new FacesUrlTransformer(path,
FacesContext.getCurrentInstance()).toRedirectViewId().toActionUrl().appendConversationIdIfNecessary(conversation.getId()).encode();
+ conversationManager(ctx).teardownConversation();
}
}
super.sendRedirect(path);
Modified:
core/trunk/impl/src/main/java/org/jboss/weld/servlet/HttpPassThruSessionBeanStore.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/servlet/HttpPassThruSessionBeanStore.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/servlet/HttpPassThruSessionBeanStore.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -44,12 +44,12 @@
public class HttpPassThruSessionBeanStore extends HttpSessionBeanStore
{
- private static final long serialVersionUID = 8923580660774253915L;
- private static final LocLogger log =
loggerFactory().getLogger(CONTEXT);
+ private static final long serialVersionUID = 8923580660774253915L;
+ private static final LocLogger log = loggerFactory().getLogger(CONTEXT);
- private HashMapBeanStore delegateBeanStore = new HashMapBeanStore();
- private boolean attachedToSession = false;
- private boolean invalidated = false;
+ private HashMapBeanStore delegateBeanStore = new HashMapBeanStore();
+ private boolean attachedToSession = false;
+ private boolean invalidated = false;
public HttpPassThruSessionBeanStore()
{
@@ -129,7 +129,7 @@
catch (IllegalStateException e)
{
// There's not a lot to do here if the session is invalidated while
- // loading this map. These beans will not be destroyed since the
+ // loading this map. These beans will not be destroyed since the
// references are lost.
delegateBeanStore.clear();
}
Modified: core/trunk/impl/src/main/java/org/jboss/weld/servlet/HttpSessionBeanStore.java
===================================================================
---
core/trunk/impl/src/main/java/org/jboss/weld/servlet/HttpSessionBeanStore.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/impl/src/main/java/org/jboss/weld/servlet/HttpSessionBeanStore.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -37,7 +37,7 @@
private static final NamingScheme NAMING_SCHEME = new
NamingScheme(SessionContext.class.getName(), "#");
// The HTTP session context to use as backing map
- private HttpSession session;
+ private HttpSession session;
/**
* Attaches this bean store to a session dynamically. This allows the session
Modified: core/trunk/impl/src/main/java/org/jboss/weld/servlet/ServletLifecycle.java
===================================================================
--- core/trunk/impl/src/main/java/org/jboss/weld/servlet/ServletLifecycle.java 2010-02-26
08:08:17 UTC (rev 5963)
+++ core/trunk/impl/src/main/java/org/jboss/weld/servlet/ServletLifecycle.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -48,7 +48,7 @@
private final ContextLifecycle lifecycle;
- public static final String REQUEST_ATTRIBUTE_NAME =
ServletLifecycle.class.getName() + ".requestBeanStore";
+ public static final String REQUEST_ATTRIBUTE_NAME = ServletLifecycle.class.getName() +
".requestBeanStore";
/**
*
Modified:
core/trunk/tests/src/test/java/org/jboss/weld/tests/serialization/SerializationTest.java
===================================================================
---
core/trunk/tests/src/test/java/org/jboss/weld/tests/serialization/SerializationTest.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/tests/src/test/java/org/jboss/weld/tests/serialization/SerializationTest.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -36,14 +36,12 @@
TestConversationManager cMgr = getReference(TestConversationManager.class);
assert cMgr.getConversationInstance() != null;
- assert cMgr.getConversationInstance().get() != null;
Object deserialized = Utils.deserialize(Utils.serialize(cMgr));
assert deserialized instanceof TestConversationManager;
TestConversationManager deserializedCMgr = (TestConversationManager) deserialized;
assert deserializedCMgr.getConversationInstance() != null;
- assert deserializedCMgr.getConversationInstance().get() != null;
}
@Test(description="http://lists.jboss.org/pipermail/weld-dev/2010-February/002265.html")
Modified:
core/trunk/tests/src/test/java/org/jboss/weld/tests/serialization/TestConversationManager.java
===================================================================
---
core/trunk/tests/src/test/java/org/jboss/weld/tests/serialization/TestConversationManager.java 2010-02-26
08:08:17 UTC (rev 5963)
+++
core/trunk/tests/src/test/java/org/jboss/weld/tests/serialization/TestConversationManager.java 2010-02-27
13:31:35 UTC (rev 5964)
@@ -19,7 +19,6 @@
import java.lang.reflect.Field;
import javax.enterprise.context.Dependent;
-import javax.enterprise.inject.Instance;
import org.jboss.weld.conversation.AbstractConversationManager;
import org.jboss.weld.conversation.ConversationImpl;
@@ -28,17 +27,13 @@
@Dependent
public class TestConversationManager extends ServletConversationManager
{
-
- /**
- *
- */
- private static final long serialVersionUID = 9081670661490776033L;
+ private static final long serialVersionUID = 2;
- public Instance<ConversationImpl> getConversationInstance() throws Exception
+ public ConversationImpl getConversationInstance() throws Exception
{
- Field ccField =
AbstractConversationManager.class.getDeclaredField("currentConversation");
+ Field ccField =
AbstractConversationManager.class.getDeclaredField("conversation");
ccField.setAccessible(true);
- return (Instance<ConversationImpl>) ccField.get(this);
+ return (ConversationImpl) ccField.get(this);
}
}