
org.jboss.weld.servlet.ConversationContextActivator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weld-servlet-shaded Show documentation
Show all versions of weld-servlet-shaded Show documentation
This jar bundles all the bits of Weld and CDI required for running in a Servlet container.
/*
* JBoss, Home of Professional Open Source
* Copyright 2013, 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.servlet;
import static org.jboss.weld.context.AbstractConversationContext.DESTRUCTION_QUEUE_ATTRIBUTE_NAME;
import static org.jboss.weld.util.reflection.Reflections.cast;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.jboss.weld.context.AbstractConversationContext;
import org.jboss.weld.context.ConversationContext;
import org.jboss.weld.context.api.ContextualInstance;
import org.jboss.weld.context.http.HttpConversationContext;
import org.jboss.weld.context.http.LazyHttpConversationContextImpl;
import org.jboss.weld.event.FastEvent;
import org.jboss.weld.literal.DestroyedLiteral;
import org.jboss.weld.literal.InitializedLiteral;
import org.jboss.weld.logging.ContextLogger;
import org.jboss.weld.logging.ConversationLogger;
import org.jboss.weld.logging.ServletLogger;
import org.jboss.weld.manager.BeanManagerImpl;
/**
* This component takes care of activation/deactivation of the conversation context for a servlet request.
*
* @see ConversationFilter
* @see org.jboss.weld.servlet.WeldInitialListener
*
* @author Jozef Hartinger
* @author Marko Luksa
*
*/
public class ConversationContextActivator {
private static final String NO_CID = "nocid";
private static final String CONVERSATION_PROPAGATION = "conversationPropagation";
private static final String CONVERSATION_PROPAGATION_NONE = "none";
private static final String CONTEXT_ACTIVATED_IN_REQUEST = ConversationContextActivator.class.getName() + ".contextActivatedInRequest";
private final BeanManagerImpl beanManager;
private HttpConversationContext httpConversationContextCache;
private final FastEvent conversationInitializedEvent;
private final FastEvent conversationDestroyedEvent;
private final Consumer lazyInitializationCallback;
private final boolean lazy;
protected ConversationContextActivator(BeanManagerImpl beanManager, boolean lazy) {
this.beanManager = beanManager;
conversationInitializedEvent = FastEvent.of(HttpServletRequest.class, beanManager, InitializedLiteral.CONVERSATION);
conversationDestroyedEvent = FastEvent.of(HttpServletRequest.class, beanManager, DestroyedLiteral.CONVERSATION);
lazyInitializationCallback = lazy ? conversationInitializedEvent::fire : null;
this.lazy = lazy;
}
private HttpConversationContext httpConversationContext() {
if (httpConversationContextCache == null) {
this.httpConversationContextCache = beanManager.instance().select(HttpConversationContext.class).get();
}
return httpConversationContextCache;
}
public void startConversationContext(HttpServletRequest request) {
associateConversationContext(request);
activateConversationContext(request);
}
public void stopConversationContext(HttpServletRequest request) {
deactivateConversationContext(request);
}
// Conversation handling
protected void activateConversationContext(HttpServletRequest request) {
HttpConversationContext conversationContext = httpConversationContext();
/*
* Don't try to reactivate the ConversationContext if we have already activated it for this request WELD-877
*/
if (!isContextActivatedInRequest(request)) {
setContextActivatedInRequest(request);
activate(conversationContext, request);
} else {
/*
* We may have previously been associated with a ConversationContext, but the reference to that context may have been lost during a Servlet forward
* WELD-877
*/
conversationContext.dissociate(request);
conversationContext.associate(request);
activate(conversationContext, request);
}
}
private void activate(HttpConversationContext conversationContext, final HttpServletRequest request) {
if (lazy) {
conversationContext.activateLazily(lazyInitializationCallback);
} else {
String cid = determineConversationId(request, conversationContext.getParameterName());
conversationContext.activate(cid);
if (cid == null) { // transient conversation
conversationInitializedEvent.fire(request);
}
}
}
protected void associateConversationContext(HttpServletRequest request) {
httpConversationContext().associate(request);
}
private void setContextActivatedInRequest(HttpServletRequest request) {
request.setAttribute(CONTEXT_ACTIVATED_IN_REQUEST, true);
}
private boolean isContextActivatedInRequest(HttpServletRequest request) {
Object result = request.getAttribute(CONTEXT_ACTIVATED_IN_REQUEST);
if (result == null) {
return false;
}
return (Boolean) result;
}
protected void deactivateConversationContext(HttpServletRequest request) {
try {
ConversationContext conversationContext = httpConversationContext();
if (conversationContext.isActive()) {
// Only deactivate the context if one is already active, otherwise we get Exceptions
if (conversationContext instanceof LazyHttpConversationContextImpl) {
LazyHttpConversationContextImpl lazyConversationContext = (LazyHttpConversationContextImpl) conversationContext;
if (!lazyConversationContext.isInitialized()) {
// if this lazy conversation has not been touched yet, just deactivate it
lazyConversationContext.deactivate();
processDestructionQueue(request);
return;
}
}
boolean isTransient = conversationContext.getCurrentConversation().isTransient();
if (ConversationLogger.LOG.isTraceEnabled()) {
if (isTransient) {
ConversationLogger.LOG.cleaningUpTransientConversation();
} else {
ConversationLogger.LOG.cleaningUpConversation(conversationContext.getCurrentConversation().getId());
}
}
conversationContext.invalidate();
conversationContext.deactivate();
if (isTransient) {
conversationDestroyedEvent.fire(request);
}
processDestructionQueue(request);
}
} catch (Exception e) {
ServletLogger.LOG.unableToDeactivateContext(httpConversationContext(), request);
ServletLogger.LOG.catchingDebug(e);
}
}
/**
* If needed, destroy the remaining conversation contexts after an HTTP session was invalidated within the current request.
*
* @param request
*/
private void processDestructionQueue(HttpServletRequest request) {
Object contextsAttribute = request.getAttribute(DESTRUCTION_QUEUE_ATTRIBUTE_NAME);
if (contextsAttribute instanceof Map) {
Map>> contexts = cast(contextsAttribute);
synchronized (contexts) {
FastEvent destroyedEvent = FastEvent.of(String.class, beanManager, DestroyedLiteral.CONVERSATION);
for (Iterator>>> iterator = contexts.entrySet().iterator(); iterator.hasNext();) {
Entry>> entry = iterator.next();
for (ContextualInstance> contextualInstance : entry.getValue()) {
destroyContextualInstance(contextualInstance);
}
// Note that for the attached/current conversation we fire the destroyed event twice because we can't reliably identify such a conversation
destroyedEvent.fire(entry.getKey());
iterator.remove();
}
}
}
}
private void destroyContextualInstance(ContextualInstance instance) {
instance.getContextual().destroy(instance.getInstance(), instance.getCreationalContext());
ContextLogger.LOG.contextualInstanceRemoved(instance, this);
}
protected void disassociateConversationContext(HttpServletRequest request) {
try {
httpConversationContext().dissociate(request);
} catch (Exception e) {
ServletLogger.LOG.unableToDissociateContext(httpConversationContext(), request);
ServletLogger.LOG.catchingDebug(e);
}
}
public void sessionCreated(HttpSession session) {
HttpConversationContext httpConversationContext = httpConversationContext();
if (httpConversationContext instanceof AbstractConversationContext) {
AbstractConversationContext, ?> abstractConversationContext = (AbstractConversationContext, ?>) httpConversationContext;
abstractConversationContext.sessionCreated();
}
}
public static String determineConversationId(HttpServletRequest request, String parameterName) {
if (request == null) {
throw ConversationLogger.LOG.mustCallAssociateBeforeActivate();
}
if (request.getParameter(NO_CID) != null) {
return null; // ignore cid; WELD-919
}
if (CONVERSATION_PROPAGATION_NONE.equals(request.getParameter(CONVERSATION_PROPAGATION))) {
return null; // conversationPropagation=none (CDI-135)
}
String cidName = parameterName;
String cid = request.getParameter(cidName);
ConversationLogger.LOG.foundConversationFromRequest(cid);
return cid;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy