Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
280 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,277 @@ | ||
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" | ||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ ]> | ||
<chapter id="contexts"> | ||
<title>Context Management</title> | ||
|
||
<section> | ||
<title>Managing the built in contexts</title> | ||
|
||
<para> | ||
Weld allows you to easiy manage the built in contexts by injecting them and calling | ||
lifecycle methods. Weld defines two types of context, <emphasis>managed</emphasis> | ||
and <emphasis>unmanaged</emphasis>. Managed contexts can be activated (allowing bean | ||
instances to be retrieved from the context), invalidated (scheduling bean instances | ||
for destruction) and deactivaed (stopping bean instances from being retrieved, and if | ||
the context has been invalidated, causing the bean instances to destroyed). Unmanaged | ||
contexts are always active; some may offer the ability to destroy instances. | ||
</para> | ||
|
||
<para> | ||
Managed contexts can either be <emphasis>bound</emphasis> or <emphasis>unbound</emphasis>. | ||
An unbound context is scoped to the thread in which it is activated (instances placed | ||
in the context in one thread are not visible in other threads), and is destroyed upon | ||
invalidation and deactivation. Bound contexts are attached to some external data store | ||
(such as the Http Session or a manually propagated map) by <emphasis>associating</emphasis> | ||
the data store with the context before calling activate, and discociating the data store | ||
after calling activate. | ||
</para> | ||
|
||
<tip> | ||
<para> | ||
Weld automatically controls context lifecycle in many scenarios such as Http Requests, | ||
EJB remote invocations, and MDB invocations. Many of the extensions for CDI offer context | ||
lifecycle for other environments, it's worth checking to see if there is a suitable extension | ||
before deciding to manage the context yourself. | ||
</para> | ||
</tip> | ||
|
||
<para> | ||
Weld provides a number of built in contexts, which are shown in <xref linkend="contexts.available"/>. | ||
</para> | ||
|
||
<table id="contexts.available"> | ||
<title>Available Contexts in Weld</title> | ||
<tgroup cols="4"> | ||
<thead> | ||
<row> | ||
<entry>Scope</entry> | ||
<entry>Qualifiers</entry> | ||
<entry>Context</entry> | ||
<entry>Notes</entry> | ||
</row> | ||
</thead> | ||
<tbody> | ||
<row> | ||
<entry><code>@Dependent</code></entry> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>DependentContext</code></entry> | ||
<entry>The dependent context is unbound and unmanaged</entry> | ||
</row> | ||
<row> | ||
<entry><code>@RequestScoped</code></entry> | ||
<entry><code>@Unbound</code></entry> | ||
<entry><code>RequestContext</code></entry> | ||
<entry>An unbound request context, useful for testing</entry> | ||
</row> | ||
<row> | ||
<entry morerows="1" valign="top"><code>@RequestScoped</code></entry> | ||
<entry><code>@Bound</code></entry> | ||
<entry><code>RequestContext</code></entry> | ||
<entry morerows="1" valign="top">A request context bound to a manually propagated map, useful for testing or non-Servlet environments</entry> | ||
</row> | ||
<row> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>BoundRequestContext</code></entry> | ||
</row> | ||
<row> | ||
<entry morerows="1" valign="top"><code>@RequestScoped</code></entry> | ||
<entry><code>@Http</code></entry> | ||
<entry><code>RequestContext</code></entry> | ||
<entry morerows="1" valign="top">A request context bound to a Servlet request, used for any Servlet based request context</entry> | ||
</row> | ||
<row> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>HttpRequestContext</code></entry> | ||
</row> | ||
<row> | ||
<entry morerows="1" valign="top"><code>@RequestScoped</code></entry> | ||
<entry><code>@Ejb</code></entry> | ||
<entry><code>RequestContext</code></entry> | ||
<entry morerows="1" valign="top">A request context bound to a an interceptor's invocation context, used for EJB invocations outside of Servlet requests</entry> | ||
</row> | ||
<row> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>EjbRequestContext</code></entry> | ||
</row> | ||
<row> | ||
<entry morerows="1" valign="top"><code>@ConversationScoped</code></entry> | ||
<entry><code>@Bound</code></entry> | ||
<entry><code>ConversationContext</code></entry> | ||
<entry morerows="1" valign="top">A conversation context bound to two manually propagated maps (one which represents the request and one which represents the session), useful for testing or non-Servlet environments</entry> | ||
</row> | ||
<row> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>BoundConversationContext</code></entry> | ||
</row> | ||
<row> | ||
<entry morerows="1" valign="top"><code>@ConversationScoped</code></entry> | ||
<entry><code>@Http</code></entry> | ||
<entry><code>ConversationContext</code></entry> | ||
<entry morerows="1" valign="top">A conversation context bound to a Servlet request, used for any Servlet based conversation context</entry> | ||
</row> | ||
<row> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>HttpConversationContext</code></entry> | ||
</row> | ||
<row> | ||
<entry morerows="1" valign="top"><code>@SessionScoped</code></entry> | ||
<entry><code>@Bound</code></entry> | ||
<entry><code>SessionContext</code></entry> | ||
<entry morerows="1" valign="top">A session context bound to a manually propagated map, useful for testing or non-Servlet environments</entry> | ||
</row> | ||
<row> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>BoundSessionContext</code></entry> | ||
</row> | ||
<row> | ||
<entry morerows="1" valign="top"><code>@SessionScoped</code></entry> | ||
<entry><code>@Http</code></entry> | ||
<entry><code>SessionContext</code></entry> | ||
<entry morerows="1" valign="top">A session context bound to a Servlet request, used for any Servlet based session context</entry> | ||
</row> | ||
<row> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>HttpSessionContext</code></entry> | ||
</row> | ||
<row> | ||
<entry><code>@ApplicationScoped</code></entry> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>ApplicationContext</code></entry> | ||
<entry>An application context backed by an application scoped singleton, it is unmanaged and unbound but does offer an option to destroy all entries</entry> | ||
</row> | ||
<row> | ||
<entry><code>@SingletonScoped</code></entry> | ||
<entry><code>@Default</code></entry> | ||
<entry><code>SingletonContext</code></entry> | ||
<entry>A singleton context backed by an application scoped singleton, it is unmanaged and unbound but does offer an option to destroy all entries</entry> | ||
</row> | ||
</tbody> | ||
</tgroup> | ||
</table> | ||
|
||
<para> | ||
Unmanaged contexts offer little of interest in a discussion about managing context lifecycles, so from here on in | ||
we will concentrate on the managed contexts (unmanaged contexts of course play a vital role in the functioning of | ||
your application and Weld!). As you can see from the table above, the managed contexts offer a number of different | ||
implmentations for the same scope; in general, each flavor of context for a scope has the same API. We'll walk through | ||
a number of common lifecycle management scenarios below; armed with this knowledge, and the Javadoc, you should be able | ||
to work with any of the context implementations Weld offers. | ||
</para> | ||
|
||
<para> | ||
We'll start simple with the <code>BoundRequestContext</code>, which you might use to provide the request scope outside of | ||
a Servlet request or EJB Invocation. | ||
</para> | ||
|
||
<programlisting role="JAVA"><![CDATA[ /* Inject the BoundRequestContext. */ | ||
/* Alternatively, you could look this up from the BeanManager */ | ||
@Inject BoundRequestContext requestContext; | ||
... | ||
/* Start the request, providing a data store which will last the lifetime of the request */ | ||
public void startRequest(Map<String, Object> requestDataStore) { | ||
// Associate the store with the context and acticate the context | ||
requestContext.associate(requestDataStore); | ||
requestContext.activate(); | ||
} | ||
/* End the request, providing the same data store as was used to start the request */ | ||
public void endRequest(Map<String, Object> requestDataStore) { | ||
try { | ||
/* Invalidate the request (all bean instances will be scheduled for destruction) */ | ||
requestContext.invalidate(); | ||
/* Deactivate the request, causing all bean instances to be destroyed (as the context is invalid) */ | ||
requestContext.deactivate(); | ||
} finally { | ||
/* Ensure that whatever happens we dissociate to prevent any memory leaks */ | ||
requestContext.dissociate(requestDataStore); | ||
} | ||
}]]></programlisting> | ||
|
||
<para> | ||
The bound session context works in much the same way, excepting that invalidating and deactivating the | ||
session context causes the any conversations in the session to be destroyed as well. The http session | ||
context and http request context also work similarly, and might be of use if you find yourself creating | ||
threads from an http request). The http session context additionally offers a method which can immediately | ||
destroy the context. | ||
</para> | ||
|
||
<note> | ||
<para> | ||
Weld's session contexts are "lazy" and don't require a session to actually exist until a bean instance | ||
must be written. | ||
</para> | ||
</note> | ||
|
||
<para> | ||
The conversation context offers a few more options, which we will walk through here. | ||
</para> | ||
|
||
<programlisting role="JAVA"><![CDATA[ @Inject BoundConversationContext conversationContext; | ||
... | ||
/* Start a transient conversation */ | ||
/* Provide a data store which will last the lifetime of the request */ | ||
/* and one that will last the lifetime of the session */ | ||
public void startTransientConversation(Map<String, Object> requestDataStore, | ||
Map<String, Object> sessionDataStore) { | ||
resumeOrStartConversation(requestDataStore, sessionDataStore, null); | ||
} | ||
/* Start a transient conversation (if cid is null) or resume a non-transient */ | ||
/* conversation. Provide a data store which will last the lifetime of the request */ | ||
/* and one that will last the lifetime of the session */ | ||
public void resumeOrStartConversation(Map<String, Object> requestDataStore, | ||
Map<String, Object> sessionDataStore, | ||
String cid) { | ||
/* Associate the stores with the context and acticate the context */ | ||
* BoundRequest just wraps the two datastores */ | ||
conversationContext.associate(new MutableBoundRequest(requestDataStore, sessionDataStore)); | ||
// Pass the cid in | ||
conversationContext.activate(cid); | ||
} | ||
/* End the conversations, providing the same data store as was used to start */ | ||
/* the request. Any transient conversations will be destroyed, any newly-promoted */ | ||
/* conversations will be placed into the session */ | ||
public void endOrPassivateConversation(Map<String, Object> requestDataStore, | ||
Map<String, Object> sessionDataStore) { | ||
try { | ||
/* Invalidate the conversation (all transient conversations will be scheduled for destruction) */ | ||
conversationContext.invalidate(); | ||
/* Deactivate the conversation, causing all transient conversations to be destroyed */ | ||
conversationContext.deactivate(); | ||
} finally { | ||
/* Ensure that whatever happens we dissociate to prevent memory leaks*/ | ||
conversationContext.dissociate(new MutableBoundRequest(requestDataStore, sessionDataStore)); | ||
} | ||
}]]></programlisting> | ||
|
||
<para> | ||
The conversation context also offers a number of properties which control the behavior of conversation expiration | ||
(after this period of inactivity the conversation will be ended and destroyed by the containber), and the duration | ||
of lock timeouts (the conversation context ensures that a single thread is accessing any bean instances by locking | ||
access, if a lock can't be obtained after a certain time Weld will error rather than continue to wait for the lock). | ||
Additionally, you can alter the name of the parameter used to transfer the conversation id (by default, <code>cid</code>). | ||
</para> | ||
|
||
<para> | ||
Weld also introduces the notion of a <code>ManagedConversation</code>, which extends the <code>Conversation</code> | ||
interface with the abilty to lock, unlock and touch (update the last used timestamp) a conversation. Finally, all | ||
non-transient conversations in a session can be obtained from the conversation context, as can the current conversation. | ||
</para> | ||
|
||
<tip> | ||
<para> | ||
Weld's conversations are not assigned ids until they become non-transient. | ||
</para> | ||
</tip> | ||
|
||
</section> | ||
|
||
<!-- | ||
vim:et:ts=3:sw=3:tw=120 | ||
--> | ||
</chapter> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters