Skip to content

Commit

Permalink
Fixes/improvements to conversation infra
Browse files Browse the repository at this point in the history
git-svn-id: http://anonsvn.jboss.org/repos/weld/ri/trunk@1418 1c488680-804c-0410-94cd-c6b725194a0e
  • Loading branch information
nickarls committed Feb 5, 2009
1 parent 63836be commit 65ea15a
Show file tree
Hide file tree
Showing 9 changed files with 137 additions and 77 deletions.
Expand Up @@ -26,6 +26,7 @@
import org.jboss.webbeans.bean.standard.ManagerBean;
import org.jboss.webbeans.bootstrap.spi.EjbDiscovery;
import org.jboss.webbeans.bootstrap.spi.WebBeanDiscovery;
import org.jboss.webbeans.conversation.ConversationImpl;
import org.jboss.webbeans.conversation.DefaultConversationManager;
import org.jboss.webbeans.conversation.JavaSEConversationTerminator;
import org.jboss.webbeans.conversation.NumericConversationIdGenerator;
Expand Down Expand Up @@ -101,6 +102,7 @@ protected void registerBeans(Iterable<Class<?>> classes)
beanDeployer.addBean(ManagerBean.of(manager));
beanDeployer.addBean(InjectionPointBean.of(manager));
beanDeployer.addClass(Transaction.class);
beanDeployer.addClass(ConversationImpl.class);
beanDeployer.addClass(DefaultConversationManager.class);
beanDeployer.addClass(JavaSEConversationTerminator.class);
beanDeployer.addClass(NumericConversationIdGenerator.class);
Expand Down
Expand Up @@ -20,7 +20,7 @@
* Generates conversation ID:s for the conversation manager
*
* @author Nicklas Karlsson
* @see org.jboss.webbeans.conversation.ConversationManager#beginConversation(String)
* @see org.jboss.webbeans.conversation.ConversationManager#beginOrRestoreConversation(String)
*/
public interface ConversationIdGenerator
{
Expand Down
Expand Up @@ -20,6 +20,9 @@
import javax.annotation.Named;
import javax.context.Conversation;
import javax.context.RequestScoped;
import javax.inject.Initializer;

import org.jboss.webbeans.conversation.bindings.ConversationInactivityTimeout;

/**
* The current conversation implementation
Expand All @@ -39,27 +42,23 @@ public class ConversationImpl implements Conversation
private long timeoutInMilliseconds;

/**
* Creates a new conversation
*
* @param cid The conversation ID
* @param timeoutInMilliseconds The inactivity timeout in milliseconds
* Creates a new conversation
*/
protected ConversationImpl(String cid, long timeoutInMilliseconds)
public ConversationImpl()
{
this.timeoutInMilliseconds = timeoutInMilliseconds;
this.cid = cid;
}

/**
* Factory method
* Initializes a new conversation
*
* @param cid The conversation ID
* @param conversationIdGenerator The conversation ID generator
* @param timeoutInMilliseconds The inactivity timeout in milliseconds
* @return A new conversation
*/
public static ConversationImpl of(String cid, long timeoutInMilliseconds)
@Initializer
public void init(ConversationIdGenerator conversationIdGenerator, @ConversationInactivityTimeout long timeoutInMilliseconds)
{
return new ConversationImpl(cid, timeoutInMilliseconds);
this.cid = conversationIdGenerator.nextId();
this.timeoutInMilliseconds = timeoutInMilliseconds;
}

public void begin()
Expand Down Expand Up @@ -105,7 +104,7 @@ public void setTimeout(long timeout)
* @param longRunning The new long-running status
* @param timeout The new inactivity timeout in milliseconds
*/
public void become(String cid, boolean longRunning, long timeoutInMilliseconds)
public void switchTo(String cid, boolean longRunning, long timeoutInMilliseconds)
{
this.cid = cid;
this.longRunning = longRunning;
Expand Down
Expand Up @@ -25,34 +25,21 @@
public interface ConversationManager
{
/**
* Begins a conversation
* Begins or restores a conversation
*
* @param cid The incoming conversation ID. Can be null in cases of transient conversations
*/
public abstract void beginConversation(String cid);
public abstract void beginOrRestoreConversation(String cid);

/**
* Ends the current conversation
* Cleans up the current conversation, destroying transient conversation and handling
* long-running conversations
*/
public abstract void endConversation();
public abstract void cleanupConversation();

/**
* Destroys all long-running conversations
*/
public abstract void destroyAllConversations();

/**
* Gets The inactivity timeout
*
* @return The timeout in milliseconds
*/
public abstract long getInactivityTimeoutInMilliseconds();

/**
* Gets The concurrent access timeout
*
* @return The timeout in milliseconds
*/
public abstract long getConcurrentAccessTimeoutInMilliseconds();

}
Expand Up @@ -21,15 +21,15 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Future;

import javax.context.Conversation;
import javax.context.RequestScoped;
import javax.context.SessionScoped;
import javax.inject.Current;
import javax.inject.Produces;
import javax.servlet.http.HttpSession;

import org.jboss.webbeans.bootstrap.WebBeansBootstrap;
import org.jboss.webbeans.context.ConversationContext;
import org.jboss.webbeans.conversation.bindings.ConversationConcurrentAccessTimeout;
import org.jboss.webbeans.conversation.bindings.ConversationInactivityTimeout;
import org.jboss.webbeans.log.LogProvider;
import org.jboss.webbeans.log.Logging;

Expand All @@ -44,21 +44,25 @@ public class DefaultConversationManager implements ConversationManager, Serializ
{
private static LogProvider log = Logging.getLogProvider(WebBeansBootstrap.class);

// The conversation id generator
@Current
private ConversationIdGenerator conversationIdGenerator;

// The conversation terminator
@Current
private ConversationTerminator conversationTerminator;

// The current conversation
@Current
private Conversation currentConversation;
private ConversationImpl currentConversation;

// The current HTTP session
@Current
private HttpSession session;

// The conversation timeout in milliseconds waiting for access to a blocked conversation
@ConversationConcurrentAccessTimeout
private long concurrentAccessTimeout;

// The conversation inactivity timeout in milliseconds
@ConversationInactivityTimeout
private long inactivityTimeout;

// A map of current active long-running conversation entries
private Map<String, ConversationEntry> longRunningConversations;
Expand All @@ -71,22 +75,22 @@ public DefaultConversationManager()
log.trace("Created " + getClass());
longRunningConversations = new ConcurrentHashMap<String, ConversationEntry>();
}

/**
* Producer method for transient conversations
*
* @return A new transient conversation
*/

@Produces
@RequestScoped
public Conversation produceNewTransientConversation()
@ConversationInactivityTimeout
public long getConversationTimeoutInMilliseconds()
{
Conversation conversation = ConversationImpl.of(conversationIdGenerator.nextId(), getInactivityTimeoutInMilliseconds());
log.trace("Produced a new conversation: " + conversation);
return conversation;
return 10 * 60 * 1000;
}

public void beginConversation(String cid)
@Produces
@ConversationConcurrentAccessTimeout
public long getConversationConcurrentAccessTimeout()
{
return 1 * 1000;
}

public void beginOrRestoreConversation(String cid)
{
if (cid == null)
{
Expand All @@ -106,9 +110,9 @@ public void beginConversation(String cid)
// if we fail
try
{
if (!longRunningConversations.get(cid).lock(getConcurrentAccessTimeoutInMilliseconds()))
if (!longRunningConversations.get(cid).lock(concurrentAccessTimeout))
{
log.info("Could not acquire conversation lock in " + getConcurrentAccessTimeoutInMilliseconds() + "ms, giving up");
log.info("Could not acquire conversation lock in " + concurrentAccessTimeout + "ms, giving up");
return;
}
}
Expand All @@ -128,11 +132,11 @@ public void beginConversation(String cid)
{
// If all goes well, set the identity of the current conversation to
// match the fetched long-running one
((ConversationImpl) currentConversation).become(cid, true, getInactivityTimeoutInMilliseconds());
currentConversation.switchTo(cid, true, inactivityTimeout);
}
}

public void endConversation()
public void cleanupConversation()
{
String cid = currentConversation.getId();
if (currentConversation.isLongRunning())
Expand Down Expand Up @@ -175,7 +179,7 @@ public void endConversation()
private Future<?> scheduleForTermination(String cid)
{
Runnable terminationTask = new TerminationTask(cid);
return conversationTerminator.scheduleForTermination(terminationTask, getInactivityTimeoutInMilliseconds());
return conversationTerminator.scheduleForTermination(terminationTask, inactivityTimeout);
}

/**
Expand Down Expand Up @@ -218,14 +222,4 @@ public void destroyAllConversations()
longRunningConversations.clear();
}

public long getConcurrentAccessTimeoutInMilliseconds()
{
return 1000;
}

public long getInactivityTimeoutInMilliseconds()
{
return 10 * 60 * 1000;
}

}
Expand Up @@ -19,15 +19,15 @@
import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;

import javax.context.ApplicationScoped;
import javax.context.SessionScoped;

/**
* A ConversationIdGenerator implementation using running numerical values
*
* @author Nicklas Karlsson
*
*/
@ApplicationScoped
@SessionScoped
public class NumericConversationIdGenerator implements ConversationIdGenerator, Serializable
{
// The next conversation ID
Expand Down
@@ -0,0 +1,42 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, 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.webbeans.conversation.bindings;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.BindingType;

/**
* The conversation context concurrent access wait timeout on a lock
*
* @author Nicklas Karlsson
*/
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@BindingType
public @interface ConversationConcurrentAccessTimeout
{
}
@@ -0,0 +1,42 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat Middleware LLC, 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.webbeans.conversation.bindings;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.ElementType.PARAMETER;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

import javax.inject.BindingType;

/**
* The conversation context inactivity timeout
*
* @author Nicklas Karlsson
*/
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@BindingType
public @interface ConversationInactivityTimeout
{
}
Expand Up @@ -104,7 +104,7 @@ public static void beginRequest(HttpServletRequest request)
private static void beginConversation(HttpServletRequest request)
{
ConversationManager conversationManager = CurrentManager.rootManager().getInstanceByType(ConversationManager.class);
conversationManager.beginConversation(request.getParameter("cid"));
conversationManager.beginOrRestoreConversation(request.getParameter("cid"));
Conversation conversation = CurrentManager.rootManager().getInstanceByType(Conversation.class);
ConversationContext.INSTANCE.setBeanMap(new ConversationBeanMap(request.getSession(), conversation.getId()));
}
Expand All @@ -119,15 +119,9 @@ public static void endRequest(HttpServletRequest request)
DependentContext.INSTANCE.setActive(false);
RequestContext.INSTANCE.destroy();
SessionContext.INSTANCE.setBeanMap(null);
endConversation();
CurrentManager.rootManager().getInstanceByType(ConversationManager.class).cleanupConversation();
ConversationContext.INSTANCE.setBeanMap(null);
CurrentManager.rootManager().getInstanceByType(SessionManager.class).setSession(null);
}

private static void endConversation()
{
ConversationManager conversationManager = CurrentManager.rootManager().getInstanceByType(ConversationManager.class);
conversationManager.endConversation();
}

}

0 comments on commit 65ea15a

Please sign in to comment.