/* * Copyright 2009 JBoss, a divison Red Hat, Inc * * 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.errai.cdi.server; import org.jboss.errai.bus.client.api.Message; import org.jboss.errai.bus.client.api.MessageCallback; import org.jboss.errai.bus.client.framework.MessageBus; import org.jboss.weld.context.bound.BoundConversationContext; import org.jboss.weld.context.bound.BoundRequestContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.enterprise.inject.spi.BeanManager; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Maintains CDI invocation context lifecyle. * * @author: Heiko Braun <hbraun@redhat.com> * @date: Sep 28, 2010 */ public class ContextManager { private static final Logger log = LoggerFactory.getLogger(ContextManager.class); private BoundRequestContext requestContext; private BoundConversationContext conversationContext; private ThreadLocal<Map<String, Object>> requestContextStore = new ThreadLocal<Map<String, Object>>(); private Map<String, ConversationContext> conversationContextStore = new ConcurrentHashMap<String, ConversationContext>(); private String uuid; private ThreadLocal<String> threadContextId = new ThreadLocal<String>(); private MessageBus bus; public ContextManager(String uuid, BeanManager beanManager, MessageBus bus) { this.bus = bus; this.uuid = uuid; this.requestContext = (BoundRequestContext) Util.lookupCallbackBean(beanManager, BoundRequestContext.class); this.conversationContext= (BoundConversationContext) Util.lookupCallbackBean(beanManager, BoundConversationContext.class); } public void activateRequestContext() { requestContextStore.set(new HashMap<String, Object>()); requestContext.associate(requestContextStore.get()); requestContext.activate(); } public void deactivateRequestContext() { requestContext.invalidate(); requestContext.deactivate(); requestContext.dissociate(requestContextStore.get()); } public void activateConversationContext(Message message) { String sessionId = Util.getSessionId(message); if(null==conversationContextStore.get(sessionId)) conversationContextStore.put(sessionId, new ConversationContext()); conversationContext.associate(conversationContextStore.get(sessionId)); // if the client does not provide a conversation id // we fall back to transient conversations (id==null) String conversationId = message.get(String.class, "cdi.conversation.id"); threadContextId.set(conversationId); // null value demotes the conversation conversationContext.activate(threadContextId.get()); // expose the conversation context to the client // TODO: wire CDI callbacks when conversation ends String subject = "cdi.conversation:Manager,conversation=" + conversationId; if(conversationId!=null && !bus.isSubscribed(subject)) { bus.subscribe(subject, new MessageCallback() { public void callback(final Message message) { if("end".equals(message.getCommandType())) { try { activateConversationContext(message); conversationContext.getCurrentConversation().end(); deactivateConversationContext(message); // TODO: properly cleanup } catch (Exception e) { log.error("Failed to end conversation", e); } } } }); } } public void deactivateConversationContext(Message message) { String sessionId = Util.getSessionId(message); if(conversationContextStore.get(sessionId)!=null) { conversationContext.deactivate(); conversationContext.dissociate(conversationContextStore.get(sessionId)); } } public String getThreadContextId() { return threadContextId.get(); } }