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:

Creating DataContext on the Spot

A new DataContext instance normally can be created using the following code:

import org.apache.cayenne.access.DataContext;
DataContext context = DataContext.createDataContext();

This approach may be used in standalone applications, where the notion of a "session" 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.

Retrieving Session-Bound DataContext in Web Applications

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:

import org.apache.cayenne.conf.ServletUtil;
import org.apache.cayenne.access.DataContext;

// assume this exists
HttpSession session;
DataContext context = ServletUtil.getSessionContext(session);

Retrieving Thread-Bound DataContext.

An application can bind a context to a current execution thread (e.g. via WebApplicationContextFilter 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 BaseContext.getThreadObjectContext() static method. If no context was bound to the current thread, this method throws IllegalStateException. Also note that it returns ObjectContext (an interface implemented by DataContext). 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.

// we are positive there is DataContext in the current thread, and do not want
// to handle possible exception...
DataContext context = (DataContext) BaseContext.getThreadObjectContext();
// we want to handle the condition of no thread-bound context...
try {
    DataContext context = (DataContext) BaseContext.getThreadObjectContext();
catch(IllegalStateException ex) {
    // handle failure

Multiple DataDomains (Advanced)

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 "customer" 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.

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.

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 "customer". Creation of DataContext in this case is done using DataDomain name as a parameter:

import org.apache.cayenne.access.DataContext;

// domain name string is initialized depending on
// the application logic. For instance it can be based
// on the logged in user's company, etc.
String domainName = ...;
DataContext context = DataContext.createDataContext(domainName);