This page contains proposals of the DeltaSpike community for CDI 1.1. Some parts might be used also for DeltaSpike for CDI 1.0.
public interface ManagedContext extends Context { void start(); void stop(); }
[TODO]
A set of dependent scoped built in beans are available for context management.
/** * <p> * Lifecycle management for built in contexts. {@link ManagedContext} only * allows a context to be activated, deactivated and destroyed. It does not * allow the context to be associated with an underlying data store. These * operations are defined on {@link BoundContext}. * </p> * * <p> * CDI provides a number of managed contexts: {@link SessionContext}, * {@link ConversationContext}, {@link RequestContext}. All these managed * contexts are scoped to the thread, and propagation of the backing store * between threads is the responsibility of the managed context user. * </p> * * @see BoundContext * */ public interface ManagedContext extends Context { /** * Activate the Context. */ public void activate(); /** * Deactivate the Context, destroying any instances if the context is invalid. */ public void deactivate(); /** * Mark the context as due for destruction when deactivate is called. */ public void invalidate(); }
b
/** * <p> * Allows a thread-based context to be bound to some external instance storage * (such as an HttpSession). * </p> * * <p> * A context may be <em>detachable</em> in which case a call to * {@link ManagedContext#invalidate()} will detach the context from it's * associated storage. A detached context is still usable (instances may be * added or removed) however changes will not be written through to the * underlying data store. * </p> * * <p> * Normally, a detachable context will have it's underlying bean store attached * on a call to {@link ManagedContext#activate()} and detached on a call to * {@link ManagedContext#deactivate()} however a subtype of {@link BoundContext} * may change this behavior. * </p> * * <p> * If you call {@link #associate(Object)} you must ensure that you call * {@link #dissociate(Object)} in all cases, otherwise you risk memory leaks. * </p> * * @param <S> the type of the external instance storage * @see ManagedContext */ public interface BoundContext<S> extends Context { /** * Associate the context with the storage (for this thread). Once * {@link #associate(Object)} has been called, further calls to * {@link #associate(Object)} will be ignored, until the context has been * subsequently {@link #dissociate(Object)} from the storage. * * @param storage the external storage * @return true if the storage was attached, otherwise false */ public boolean associate(S storage); /** * Dissociate the context from the storage (for this thread). The context * will only dissociate from the same storage it associated with. * * @param storage the external storage * @return true if the storage was dissociated */ public boolean dissociate(S storage); } /** * <p> * The built in dependent context, associated with {@link Dependent}. It is * always active. * </p> * * <p> * There is one Dependent context which can be injected using: * </p> * * <pre> * @Inject DependentContext dependentContext; * </pre> * */ public interface DependentContext extends Context { }
b
/** * <p> * The built in request context is associated with {@link RequestScoped} and is * a managed context which can be activated, invalidated and deactivated. * </p> * * <p> * CDI comes with one implementation of the request context. The * {@link HttpRequestContext}, in which conversations are bound to the * {@link ServletRequest}, can be injected: * </p> * * <pre> * @Inject @Http RequestContext requestContext; * </pre> * * @see HttpRequestContext * @see RequestScoped * */ public interface RequestContext extends ManagedContext {}
b
/** * <p> * The built in session context is associated with {@link SessionScoped}. It can * be activated, invalidated and deactivated. * </p> * * <p> * CDI comes with one implementation of the session context. The * {@link HttpSessionContext}, in which conversations are bound to the * {@link HttpSession}, can be injected: * </p> * * <pre> * @Inject @Http SessionContext sessionContext; * </pre> * * @see HttpSessionContext * @sees {@link SessionScoped} * */ public interface SessionContext extends ManagedContext {}
b
/** * <p> * The built in application context, associated with {@link ApplicationScoped}. * It is always active (not managed) and is backed by an application scoped * singleton. * </p> * * <p> * CDI comes with one Application context which can be injected using: * </p> * * <pre> * @Inject ApplicationContext applicationContext; * </pre> * * @see SingletonContext * @see ApplicationScoped * */ public interface ApplicationContext extends Context { /** * Invalidate the context, causing all bean instances to be destroyed. */ public void invalidate(); }
b
/** * <p> * The built in singleton context, associated with {@link Singleton}. * It is always active (not managed) and is backed by an application scoped * singleton. * </p> * * <p> * CDI comes with one Singleton context which can be injected using: * </p> * * <pre> * @Inject SingletonContext singletonContext; * </pre> * * @author Pete Muir * @see SingletonContext * @see ApplicationScoped * */ public interface SingletonContext extends Context {}
And these HTTP backed implementations:
/** * <p> * A request context which can be bound to the {@link ServletRequest}. The * context is automatically attached to the map on activation, and detached when * {@link #invalidate()} is called. * </p> * * <p> * This context is not thread safe, and provides no thread safety for the * underlying map. * </p> * */ public interface HttpRequestContext extends BoundContext<ServletRequest>, RequestContext {}
b
/** * <p> * A session context which can be bound to the {@link HttpServletRequest}. The * context is automatically attached to the map on activation, and detached when * {@link #invalidate()} is called. * </p> * * <p> * This context is not thread safe, and provides no thread safety for the * underlying map. * </p> * */ public interface HttpSessionContext extends BoundContext<HttpServletRequest>, SessionContext { /** * <p> * Mark the Session Context for destruction; the Session Context will be * detached from the underling Http Session, and instances marked for * destruction when the Http Request is destroyed. * </p> * */ public void invalidate(); /** * <p> * Destroy the session and all conversations stored in the session. * </p> * * <p> * If the context is not currently associated with a * {@link HttpServletRequest}, then the context will be associated with the * specified {@link HttpSession} (for this thread), activated, destroyed, and * then deactivated. * </p> * * <p> * If the context is already associated with a {@link HttpServletRequest} * then this call will detach the context from the underlying Http Session, * and mark the context for destruction when the request is destroyed. * </p> * * @param session the {@link HttpSession} in which to store the bean * instances * @return true if the context was destroyed immediately */ public boolean destroy(HttpSession session); }
We may also wish to add map-bound contexts, in which the contexts are backed by a map. Note that the example javadoc above needs expanding if we do.
Add these dependent scoped beans:
/** * <p> * Allows a thread-based context to be bound to some external instance storage * (such as an HttpSession). * </p> * * <p> * A context may be <em>detachable</em> in which case a call to * {@link ManagedContext#invalidate()} will detach the context from it's * associated storage. A detached context is still usable (instances may be * added or removed) however changes will not be written through to the * underlying data store. * </p> * * <p> * Normally, a detachable context will have it's underlying bean store attached * on a call to {@link ManagedContext#activate()} and detached on a call to * {@link ManagedContext#deactivate()} however a subtype of {@link BoundContext} * may change this behavior. * </p> * * <p> * If you call {@link #associate(Object)} you must ensure that you call * {@link #dissociate(Object)} in all cases, otherwise you risk memory leaks. * </p> * * @param <S> the type of the external instance storage * @see ManagedContext */ public interface BoundContext<S> extends Context { /** * Associate the context with the storage (for this thread). Once * {@link #associate(Object)} has been called, further calls to * {@link #associate(Object)} will be ignored, until the context has been * subsequently {@link #dissociate(Object)} from the storage. * * @param storage the external storage * @return true if the storage was attached, otherwise false */ public boolean associate(S storage); /** * Dissociate the context from the storage (for this thread). The context * will only dissociate from the same storage it associated with. * * @param storage the external storage * @return true if the storage was dissociated */ public boolean dissociate(S storage); }
b
/** * <p> * A request context which can be bound to any Map. The context is automatically * attached to the map on activation, and detached when {@link #invalidate()} is * called. * </p> * * <p> * This context is not thread safe, and provides no thread safety for the * underlying map. A thread-safe map can be used to back the context. * </p> */ public interface BoundRequestContext extends RequestContext, BoundContext<Map<String, Object>> {}
b
/** * <p> * A session context which can be bound to any Map. The context is automatically * attached to the map on activation, and detached when {@link #invalidate()} is * called. * </p> * * <p> * This context is not thread safe, and provides no thread safety for the * underlying map. A thread-safe map can be used to back the context. * </p> * */ public interface BoundSessionContext extends SessionContext, BoundContext<Map<String, Object>> {}
As always, conversations are harder to model. In this case, we need to provide both a map for the "session" (in which a conversation may stored long term) and a map for the current "request".
/** * <p> * A conversation is used to span multiple requests, however is shorter than a * session. The {@link BoundConversationContext} uses one Map to represent a * request, and a second to represent the session, which are encapsulated in a * {@link BoundRequest}. * </p> * */ public interface BoundRequest { /** * Get the current request map. * * @return */ public Map<String, Object> getRequestMap(); /** * <p> * Get the current session map. * </p> * * <p> * A {@link BoundRequest} may be backed by a data store that only creates * sessions on demand. It is recommended that if the session is not created * on demand, or that the session has already been created (but is not * required by this access) that the session is returned as it allows the * conversation context to work more efficiently. * </p> * * @param create if true, then a session must be created * @return the session map; null may be returned if create is false */ public Map<String, Object> getSessionMap(boolean create); }
/** * <p> * The built in conversation context is associated with * {@link ConversationScoped}. It can be activated, invalidated and deactivated. * and provides various options for configuring conversation defaults. * </p> * * <p> * CDI comes with one implementation of the conversation context. The * {@link HttpConversationContext}, in which conversations are bound to the * {@link HttpSession}, can be injected: * </p> * * <pre> * @Inject @Http ConversationContext conversationContext; * </pre> * * @see BoundConversationContext * @see HttpConversationContext * @see ConversationScoped * */ public interface ConversationContext extends ManagedContext { /** * Cause any expired conversations to be ended, and therefore marked for * destruction when deactivate is called. * * @throws IllegalStateException if the context is unable to access the * underlying data store */ public void invalidate(); /** * Activate the conversation context, using the id provided to attempt to * restore a long-running conversation * * @param cid if the cid is null, a transient conversation will be created, * otherwise the conversation will be restored * @throws IllegalStateException if the context is unable to access the * underlying data store */ public void activate(String cid); /** * Activate the conversation context, starting a new transient conversation * * @throws IllegalStateException if the context is unable to access the * underlying data store */ public void activate(); /** * Set the name of the parameter used to propagate the conversation id * * @param cid the name of the conversation id parameter */ public void setParameterName(String cid); /** * Get the name of the parameter used to propagate the conversation id * * @return the name of the conversation id parameter */ public String getParameterName(); /** * Set the concurrent access timeout * * @param timeout the timeout (in ms) for the concurrent access lock */ public void setConcurrentAccessTimeout(long timeout); /** * Get the current concurrent access timeout * * @return the timeout (in ms) for the concurrent access lock */ public long getConcurrentAccessTimeout(); /** * Set the default inactivity timeout. This may be overridden on a per * conversation basis using {@link Conversation#setTimeout(long)} * * @param timeout the default inactivity timeout (in ms) */ public void setDefaultTimeout(long timeout); /** * Get the default inactivity timeout. This may have been overridden on a per * conversation basis. * * @return the default inactivity timeout (in ms) */ public long getDefaultTimeout(); /** * Get conversations currently known to the context. This will include any * non transient conversations, as well as any conversations which were * previously long running and have been made transient during this request. * * @return a collection containing the conversations * * @throws IllegalStateException if the context is unable to access the * underlying data store */ public Collection<ManagedConversation> getConversations(); /** * Get the conversation with the given id. * * @param id the id of the conversation to get * @return the conversation, or null if no conversation is known * * @throws IllegalStateException if the context is unable to access the * underlying data store */ public ManagedConversation getConversation(String id); /** * Generate a new, unique, conversation id * * @return a new, unique conversation id * * @throws IllegalStateException if the context is unable to access the * underlying data store */ public String generateConversationId(); /** * Get a handle the current conversation (transient or otherwise). * * @return the current conversation * @throws IllegalStateException if the context is unable to access the * underlying data store */ public ManagedConversation getCurrentConversation(); }
b
package org.jboss.weld.context; import javax.enterprise.context.ContextNotActiveException; import javax.enterprise.context.Conversation; /** * <p> * Provides management operations for conversations, including locking, and * expiration management. * </p> * * @see ConversationContext * */ public interface ManagedConversation extends Conversation { /** * Attempts to unlock the conversation * * @throws ContextNotActiveException if the conversation context is not * active * @return true if the unlock was successful, false otherwise */ public boolean unlock(); /** * 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 * @throws * @throws ContextNotActiveException if the conversation context is not * active */ public boolean lock(long timeout); /** * Gets the last time the conversation was used (for data access) * * @return time (in ms) since the conversation was last used * @throws ContextNotActiveException if the conversation context is not * active */ public long getLastUsed(); /** * Touches the managed conversation, updating the "last used" timestamp * * @throws ContextNotActiveException if the conversation context is not * active */ public void touch(); }
b
/** * <p> * A conversation context which can be bound to a pair of Maps encapsulated by * {@link BoundRequest}. The context is automatically attached to the bound * request on activation, and detached when {@link #invalidate()} is called. * </p> * * <p> * The {@link BoundConversationContext} is detachable, and transient * conversations are only attached at the end of a request. * </p> * * <p> * This context is not thread safe, and provides no thread safety for the * underlying map. A thread-safe map can be used to back the context - in this * case the map can be used as an underlying store in multiple threads safely. * </p> * */ public interface BoundConversationContext extends ConversationContext, BoundContext<BoundRequest> { /** * Destroy all conversations in the session. * * @param session the session for which to destroy all conversations * @return */ public boolean destroy(Map<String, Object> session); }
b
/** * An Http Session backed conversation context. A transient conversation will be * detached from the underlying session. If the conversation is promoted to long * running, context will be attached to the underlying Http Session at the end * of the request. * */ public interface HttpConversationContext extends BoundContext<HttpServletRequest>, ConversationContext { /** * <p> * If the context is not currently associated with a * {@link HttpServletRequest}, then the context will be associated with the * specified {@link HttpSession} (for this thread), activated, destroyed, and * then deactivated. Any conversations associated with the context will also * be destroyed. * </p> * * <p> * If the context is already associated with a {@link HttpServletRequest} * then this call will detach the context from the underlying Http Session, * and mark the context for destruction when the request is destroyed. * </p> * * <p> * This will cause any transient conversations, and any long running * conversations associated with the session, to be destroyed. * </p> * * @param session the {@link HttpSession} in which to store the bean * instances * @return true if the context was destroyed immediately */ public boolean destroy(HttpSession session); }