blob: 1008a1b0e3a48321b8e393c7c5b72f59b1c2d755 [file] [log] [blame]
Title: Obtaining DataContext
<P>Depending on deployment environment and application needs, Cayenne can be configured in a few different ways to make DataContext instances available. This is discussed in detail in deployment chapter. In this chapter we assume a properly deployed application and will concentrate on how to obtain a DataContext for the database access. The following are the most common ways to achieve that:</P>
<H3><A name="ObtainingDataContext-CreatingDataContextontheSpot"></A>Creating DataContext on the Spot</H3>
<P>A new DataContext instance normally can be created using the following code:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java"><SPAN class="code-keyword">import</SPAN> org.apache.cayenne.access.DataContext;
...
DataContext context = DataContext.createDataContext();</PRE>
</DIV></DIV>
<P>This approach may be used in standalone applications, where the notion of a &quot;session&quot; is user-defined. In web applications the correct instance of DataContext is usually bound to a session or a request thread externally, and all that is needed is to retrieve it, as discussed below. Creating a new DataContext for each request is not a recommended practice.</P>
<H3><A name="ObtainingDataContext-RetrievingSessionBoundDataContextinWebApplications"></A>Retrieving Session-Bound DataContext in Web Applications</H3>
<P>A web application can be configured to automatically create a new instance of DataContext for each new HttpSession, and set it as a session attribute. Retrieving it from a session is done with the following code:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java"><SPAN class="code-keyword">import</SPAN> org.apache.cayenne.conf.ServletUtil;
<SPAN class="code-keyword">import</SPAN> org.apache.cayenne.access.DataContext;
...
<SPAN class="code-comment">// assume <SPAN class="code-keyword">this</SPAN> exists
</SPAN>HttpSession session;
DataContext context = ServletUtil.getSessionContext(session);</PRE>
</DIV></DIV>
<H3><A name="ObtainingDataContext-RetrievingThreadBoundDataContext."></A>Retrieving Thread-Bound DataContext.</H3>
<P>An application can bind a context to a current execution thread (e.g. via <TT>WebApplicationContextFilter</TT> or manually). Later on the code that needs DB access can retrieve this DataContext without making any assumptions about the environment. This approach is universal and works in all types of applications (web, standalone, etc.). Previously bound context can be retrieved by calling <TT>BaseContext.getThreadObjectContext()</TT> static method. If no context was bound to the current thread, this method throws IllegalStateException. Also note that it returns <TT>ObjectContext</TT> (an interface implemented by <TT>DataContext</TT>). If you need to use DataContext API not declared in ObjectContext, you may use a cast, but if you don't, we recommend to stick with ObjectContext in your code, as it makes the code more flexible and portable to the future versions of Cayenne.</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java"><SPAN class="code-comment">// we are positive there is DataContext in the current thread, and <SPAN class="code-keyword">do</SPAN> not want
</SPAN><SPAN class="code-comment">// to handle possible exception...
</SPAN>DataContext context = (DataContext) BaseContext.getThreadObjectContext();</PRE>
</DIV></DIV>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java"><SPAN class="code-comment">// we want to handle the condition of no thread-bound context...
</SPAN><SPAN class="code-keyword">try</SPAN> {
DataContext context = (DataContext) BaseContext.getThreadObjectContext();
}
<SPAN class="code-keyword">catch</SPAN>(IllegalStateException ex) {
<SPAN class="code-comment">// handle failure
</SPAN> ....
}</PRE>
</DIV></DIV>
<H3><A name="ObtainingDataContext-MultipleDataDomains%28Advanced%29"></A>Multiple DataDomains (Advanced)</H3>
<P>Cayenne can be configured to support mass database hosting. This is a so-called Application Service Provider (ASP) scenario. Basic architecture of such setup is a single application supporting multiple databases (or more generally - data sources), each one with same or similar schema. Each data source corresponds to an individual ASP &quot;customer&quot; using the system. Each customer has a number of users that will log in to the system and are only allowed to view data from their data source.</P>
<P>This approach, though not required for most normal applications, could be quiet common and powerful in some enterprise systems. To implement it, each DataContext must be limited to access only a relevant subset of datasources.</P>
<P>Considering that behind the scenes a source of DataContext instances is an object called DataDomain, Cayenne allows creation of multiple DataDomains per project. Each DataDomain would support a single &quot;customer&quot;. Creation of DataContext in this case is done using DataDomain name as a parameter:</P>
<DIV class="code panel" style="border-width: 1px;"><DIV class="codeContent panelContent">
<PRE class="code-java"><SPAN class="code-keyword">import</SPAN> org.apache.cayenne.access.DataContext;
...
<SPAN class="code-comment">// domain name string is initialized depending on
</SPAN><SPAN class="code-comment">// the application logic. For instance it can be based
</SPAN><SPAN class="code-comment">// on the logged in user's company, etc.
</SPAN><SPAN class="code-object">String</SPAN> domainName = ...;
DataContext context = DataContext.createDataContext(domainName);</PRE>
</DIV></DIV>