blob: 0fb0242f8955f5ab26ab606705885c6f32934afa [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title xmlns:d="http://docbook.org/ns/docbook">Chapter&nbsp;5.&nbsp;Starting Cayenne</title><link rel="stylesheet" type="text/css" href="css/cayenne-doc.css"><meta xmlns:d="http://docbook.org/ns/docbook" name="keywords" content="Cayenne 3.1 documentation"><meta xmlns:d="http://docbook.org/ns/docbook" name="description" content="User documentation for Apache Cayenne version 3.1"><link rel="home" href="index.html" title="Cayenne Guide"><link rel="up" href="cayenne-guide-part2.html" title="Part&nbsp;II.&nbsp;Cayenne Framework"><link rel="prev" href="including-cayenne-in-project.html" title="Chapter&nbsp;4.&nbsp;Including Cayenne in a Project"><link rel="next" href="persistent-objects-objectcontext.html" title="Chapter&nbsp;6.&nbsp;Persistent Objects and ObjectContext"><script xmlns:d="http://docbook.org/ns/docbook" type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-7036673-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div xmlns:d="http://docbook.org/ns/docbook" class="navheader"><table width="100%" summary="Navigation header"><tr><th class="versioninfo">v.3.1 (3.1)</th><th align="center">Chapter&nbsp;5.&nbsp;Starting Cayenne</th><th></th></tr><tr><td width="20%" align="left"><a accesskey="p" href="including-cayenne-in-project.html">Prev</a>&nbsp;</td><th width="60%" align="center"><a accesskey="u" href="cayenne-guide-part2.html">Part&nbsp;II.&nbsp;Cayenne Framework</a></th><td width="20%" align="right">&nbsp;<a accesskey="n" href="persistent-objects-objectcontext.html">Next</a></td></tr></table><hr></div><div class="chapter" title="Chapter&nbsp;5.&nbsp;Starting Cayenne"><div class="titlepage"><div><div><h2 class="title"><a name="starting-cayenne"></a>Chapter&nbsp;5.&nbsp;Starting Cayenne</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="section"><a href="starting-cayenne.html#starting-serverruntime">Starting and Stopping ServerRuntime</a></span></dt><dt><span class="section"><a href="starting-cayenne.html#d0e963">Merging Multiple Projects</a></span></dt><dt><span class="section"><a href="starting-cayenne.html#webapps">Web Applications</a></span></dt></dl></div><div class="section" title="Starting and Stopping ServerRuntime"><div class="titlepage"><div><div><h2 class="title"><a name="starting-serverruntime"></a>Starting and Stopping ServerRuntime</h2></div></div></div><p>In runtime Cayenne is accessed via
<code class="code">org.apache.cayenne.configuration.server.ServerRuntime</code>. ServerRuntime is
created simply by calling a
constructor:</p><pre class="programlisting">ServerRuntime runtime = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> ServerRuntime(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"com/example/cayenne-project.xml"</span>);</pre><p>The parameter you pass to the constructor is a location of the main project file. Location
is a '/'-separated path (same path separator is used on UNIX and Windows) that is
resolved relative to the application classpath. The project file can be placed in the
root package or in a subpackage (e.g. in the code above it is in "com/example"
subpackage).</p><p>ServerRuntime encapsulates a single Cayenne stack. Most applications will just have
one ServerRuntime using it to create as many ObjectContexts as needed, access the
Dependency Injection (DI) container and work with other Cayenne features. Internally
ServerRuntime is just a thin wrapper around the DI container. Detailed features of the
container are discussed in "Customizing Cayenne Runtime" chapter. Here we'll just show
an example of how an application might replace a default implementation of a built-in
Cayenne service (in this case - QueryCache) with a different
class:</p><pre class="programlisting"><span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">public</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span> MyExtensionsModule <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">implements</span> Module {
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">public</span> <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">void</span> configure(Binder binder) {
binder.bind(QueryCache.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>).to(EhCacheQueryCache.<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">class</span>);
}
}</pre><pre class="programlisting">Module extensions = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> MyExtensionsModule();
ServerRuntime runtime = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> ServerRuntime(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"com/example/cayenne-project.xml"</span>, extensions);</pre><p>It is a good idea to shut down the runtime when it is no longer needed, usually before the
application itself is shutdown: </p><pre class="programlisting">runtime.shutdown();</pre><p>When
a runtime object has the same scope as the application, this may not be always
necessary, however in some cases it is essential, and is generally considered a good
practice. E.g. in a web container hot redeploy of a webapp will cause resource leaks and
eventual OutOfMemoryError if the application fails to shutdown CayenneRuntime.</p></div><div class="section" title="Merging Multiple Projects"><div class="titlepage"><div><div><h2 class="title"><a name="d0e963"></a>Merging Multiple Projects</h2></div></div></div><p>ServerRuntime requires at least one mapping project to run. But it can also take multiple
projects and merge them together in a single configuration. This way different parts of
a database can be mapped independenlty from each other (even by different software
providers), and combined in runtime when assembling an application. Doing it is as easy
as passing multiple project locations to ServerRuntime constructor:</p><pre class="programlisting">ServerRuntime runtime = <span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> ServerRuntime(<span xmlns="http://www.w3.org/1999/xhtml" class="hl-keyword">new</span> String[] {
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"com/example/cayenne-project.xml"</span>,
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"org/foo/cayenne-library1.xml"</span>,
<span xmlns="http://www.w3.org/1999/xhtml" class="hl-string">"org/foo/cayenne-library2.xml"</span>
}
);</pre><p>When the projects are merged, the following rules are applied:</p><div class="itemizedlist"><ul class="itemizedlist"><li class="listitem"><p>The order of projects matters during merge. If there are two conflicting
metadata objects belonging to two projects, an object from the <span class="italic">last</span> project takes precedence over the object
from the first one. This makes possible to override pieces of metadata. This
is also similar to how DI modules are merged in Cayenne.</p></li><li class="listitem"><p>Runtime DataDomain name is set to the name of the last project in the
list.</p></li><li class="listitem"><p>Runtime DataDomain properties are the same as the properties of the last
project in the list. I.e. <span class="italic">properties are not
merged</span> to avoid invalid combinations and unexpected runtime
behavior.</p></li><li class="listitem"><p>If there are two or more DataMaps with the same name, only one DataMap is
used in the merged project, the rest are discarded. Same precedence rules
apply - DataMap from the project with the highest index in the project list
overrides all other DataMaps with the same name.</p></li><li class="listitem"><p>If there are two or more DataNodes with the same name, only one DataNodes
is used in the merged project, the rest are discarded. DataNode coming from
project with the highest index in the project list is chosen per precedence
rule above.</p></li><li class="listitem"><p>There is a notion of "default" DataNode. After the merge if any DataMaps
are not explicitly linked to DataNodes, their queries will be executed via a
default DataNode. This makes it possible to build mapping "libraries" that
are only associated with a specific database in runtime. If there's only one
DataNode in the merged project, it will be automatically chosen as default.
A possible way to explicitly designate a specific node as default is to
override <code class="code">DataDomainProvider.createAndInitDataDomain()</code>.</p></li></ul></div></div><div class="section" title="Web Applications"><div class="titlepage"><div><div><h2 class="title"><a name="webapps"></a>Web Applications</h2></div></div></div><p>Web applications can use a variety of mechanisms to configure and start the "services"
they need, Cayenne being one of such services. Configuration can be done within standard
Servlet specification objects like Servlets, Filters, or ServletContextListeners, or can
use Spring, JEE CDI, etc. This is a user's architectural choice and Cayenne is agnostic
to it and will happily work in any environment. As described above, all that is needed
is to create an instance of ServerRuntime somewhere and provide the application code
with means to access it. And shut it down when the application ends to avoid container
leaks.</p><p>Still Cayenne includes a piece of web app configuration code that can assist in
quickly setting up simple Cayenne-enabled web applications. We are talking about
CayenneFilter. It is declared in
web.xml:</p><pre class="programlisting">&lt;web-app&gt;
...
&lt;filter&gt;
&lt;filter-name&gt;cayenne-project&lt;/filter-name&gt;
&lt;filter-class&gt;org.apache.cayenne.configuration.web.CayenneFilter&lt;/filter-class&gt;
&lt;/filter&gt;
&lt;filter-mapping&gt;
&lt;filter-name&gt;cayenne-project&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
...
&lt;/web-app&gt; </pre><p>When started by the web container, it creates a instance of ServerRuntime and stores
it in the ServletContext. Note that the name of Cayenne XML project file is derived from
the "filter-name". In the example above CayenneFilter will look for an XML file
"cayenne-project.xml". This can be overridden with "configuration-location" init
parameter.</p><p>When the application runs, all HTTP requests matching the filter url-pattern will have
access to a session-scoped ObjectContext like
this:</p><pre class="programlisting">ObjectContext context = BaseContext.getThreadObjectContext();</pre><p>Of
course the ObjectContext scope, and other behavior of the Cayenne runtime can be
customized via dependency injection. For this another filter init parameter called
"extra-modules" is used. "extra-modules" is a comma or space-separated list of class
names, with each class implementing Module interface. These optional custom modules are
loaded after the the standard ones, which allows users to override all standard
definitions.</p><p>For those interested in the DI container contents of the runtime created by CayenneFilter,
it is the same ServerRuntime as would've been created by other means, but with an extra
<code class="code">org.apache.cayenne.configuration.web.WebModule</code> module that provides
<code class="code">org.apache.cayenne.configuration.web.RequestHandler</code> service. This is
the service to override in the custom modules if you need to provide a different
ObjectContext scope, etc.</p><p>
</p><div class="note" title="Note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title">Note</h3><p>You should not think of CayenneFilter as the only way to start and use Cayenne in a web
application. In fact CayenneFilter is entirely optional. Use it if you don't
have any special design for application service management. If you do, simply
integrate Cayenne into that design.</p></div><p>
</p></div></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="including-cayenne-in-project.html">Prev</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="cayenne-guide-part2.html">Up</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="persistent-objects-objectcontext.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">Chapter&nbsp;4.&nbsp;Including Cayenne in a Project&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html">Home</a></td><td width="40%" align="right" valign="top">&nbsp;Chapter&nbsp;6.&nbsp;Persistent Objects and ObjectContext</td></tr></table></div></body></html>