blob: 740d1c9a12ff0c2f0804bc341cc82034985f47e7 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.3">
<link rel="apple-touch-icon" sizes="180x180" href="/img/favicon/apple-touch-icon-04cb17e028.png">
<link rel="icon" type="image/png" sizes="32x32" href="/img/favicon/favicon-32x32-12431ee8eb.png">
<link rel="icon" type="image/png" sizes="16x16" href="/img/favicon/favicon-16x16-4f316e4d55.png">
<link rel="manifest" href="/img/favicon/manifest-65e6aaa49e.json">
<link rel="mask-icon" href="/img/favicon/safari-pinned-tab-558c1991b1.svg" color="#dc5656">
<link rel="shortcut icon" href="/img/favicon/favicon-6cef91375b.ico">
<meta name="msapplication-TileColor" content="#ffffff">
<meta name="msapplication-TileImage" content="/img/favicon/mstile-144x144-34e7696278.png">
<meta name="msapplication-config" content="/img/favicon/browserconfig-82ff158058.xml">
<meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="https://cayenne.apache.org/css/styles-9ee2e6e330.css"/>
<script src="https://cayenne.apache.org/js/bundle-c0e6356367.js"></script>
<title>Guide to 3.1 Features &middot; Apache Cayenne</title>
</head>
<body data-spy="scroll" data-target=".toc-side" class="cd-head">
<header class="page-header">
<nav id="topbar" class="bg-dark" aria-label="breadcrumb" role="navigation">
<ul class="breadcrumb breadcrumb-sm breadcrumb-dark container mb-0">
<li class="breadcrumb-item dropdown">
<a class="dropdown-toggle text-nowrap pr-1" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img class="mw-15px mr-1" src="/img/feather-641aa69d09.svg" />Apache Software Foundation</a>
<div class="dropdown-menu rounded-0" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="https://www.apache.org">Apache Homepage</a>
<a class="dropdown-item" href="https://www.apache.org/licenses/">License</a>
<a class="dropdown-item" href="https://www.apache.org/foundation/sponsorship.html">Sponsorship</a>
<a class="dropdown-item" href="https://www.apache.org/foundation/thanks.html">Thanks</a>
<a class="dropdown-item" href="https://www.apache.org/security/">Security</a>
<a class="dropdown-item" href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy</a>
<a class="ml-1 mt-1 acevent" data-format="wide" data-mode="dark" data-width="120"></a>
</div>
</li>
</ul>
</nav>
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
<div class="container">
<a class="navbar-brand" href="https://cayenne.apache.org/">
<img src="/img/logo_mono_full-d7a19eef61.svg" alt="Apache Cayenne" />
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#mainMenu" aria-controls="mainMenu" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="mainMenu">
<ul class="navbar-nav mt-3 mt-lg-0 mr-auto">
<li class="nav-item">
<a class="nav-link" href="/download/">DOWNLOAD</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/docs/4.2/getting-started-guide/">DOCUMENTATION</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/about/support/">SUPPORT</a>
</li>
</ul>
<ul class="navbar-nav flex-row justify-content-center mt-2 mt-lg-0 mb-2 mb-lg-0 " id="social-links-menu">
<li class="nav-item d-flex">
<a class="nav-link d-flex justify-content-center align-items-center" href="https://github.com/apache/cayenne">
<img src="/img/icon_octocat_stars-c24dac94b8.svg" alt="GitHub" />
</a>
</li>
<li class="nav-item d-flex">
<a class="nav-link d-flex justify-content-center align-items-center" href="https://twitter.com/ApacheCayenne">
<img src="/img/icon_twitter-220a129d14.svg" alt="Twitter" />
</a>
</li>
</ul>
</div>
</div>
</nav>
</header>
<main>
<div class="cd-top-sidebar bb">
<div class="container">
<div class="row no-gutters">
<div class="col-12 col-lg-4 col-xl-3 br cd-sidebar1">
<ul class="nav" role="tablist">
<li class="nav-item dropdown mw-100">
<a class="nav-link dropdown-toggle text-truncate" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">
Cayenne Version 3.1
</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="/docs/5.0/cayenne-guide/">Version 5.0 (Alpha)</a><a class="dropdown-item" href="/docs/4.2/getting-started-guide/">Version 4.2 (Stable)</a><a class="dropdown-item" href="/docs/4.1/getting-started-guide/">Version 4.1 (Stable)</a><a class="dropdown-item" href="/docs/4.0/getting-started-guide/">Version 4.0 (Aging)</a><a class="dropdown-item" href="/docs/3.1/getting-started-guide/">Version 3.1 (Legacy)</a>
</div>
</li>
</ul>
</div>
<div class="col-12 col-lg-8 col-xl-9"> </div>
</div>
</div>
</div>
<div class="container">
<div class="row no-gutters ">
<div class="col-12 col-lg-4 col-xl-3 br py-2 bg-gray-100 cd-sidebar">
<div class="tab-content" id="cd-docs-nav">
<div class="cd-toc-item">
<a class="cd-toc-link" href="/docs/3.1/getting-started-guide/">Getting Started</a>
</div>
<div class="cd-toc-item">
<a class="cd-toc-link" href="/docs/3.1/cayenne-guide/">Cayenne Guide</a>
</div>
<div class="cd-toc-item">
<a class="cd-toc-link" href="/docs/3.1/getting-started-rop/">Getting Started ROP</a>
</div>
<div class="cd-toc-item">
<span class="cd-toc-link active">Upgrade Guide</span><div id="toc" class="toc toc-side">
<div id="toctitle">
Table of Contents
</div>
<ul class="sectlevel1 nav">
<li><a href="#guide-to-3-1-features" class="nav-link">1. Guide to 3.1 Features</a>
<ul class="sectlevel2 nav">
<li><a href="#distribution-contents-structure" class="nav-link">1.1. Distribution Contents Structure</a></li>
<li><a href="#cayenne-configuration" class="nav-link">1.2. Cayenne Configuration</a></li>
<li><a href="#framework-api" class="nav-link">1.3. Framework API</a></li>
<li><a href="#cayennemodeler" class="nav-link">1.4. CayenneModeler</a></li>
<li><a href="#lifecycle-extensions" class="nav-link">1.5. Lifecycle Extensions</a></li>
</ul> </li>
</ul>
</div>
</div>
<div class="cd-toc-item">
<a class="cd-toc-link" href="/docs/Apache_Cayenne_v3.1_javadoc.zip">Download JavaDoc</a></div>
</div>
</div>
<div class="col-12 col-lg-8 col-xl-9 py-3 pl-lg-5 cd-content">
<article>
<header>
<h1>Guide to 3.1 Features</h1>
</header>
<section>
<div class="sect1">
<h2 id="guide-to-3-1-features"><a class="anchor" href="#guide-to-3-1-features"></a>1. Guide to 3.1 Features</h2>
<div class="sectionbody">
<div class="paragraph">
<p>This guide highlights the new features and changes introduced in 3.1 release. It is a high-level overview. For more details consult <strong>RELEASE-NOTES.txt</strong> file included in each release for the full list of changes, and UPGRADE.txt for the release-specific upgrade instructions.</p>
</div>
<div class="sect2">
<h3 id="distribution-contents-structure"><a class="anchor" href="#distribution-contents-structure"></a>1.1. Distribution Contents Structure</h3>
<div class="paragraph">
<p>Cayenne distribution is made leaner and more modular:</p>
</div>
<div class="ulist">
<ul>
<li> <p>"cayenne-modeler.jar" is no longer included in the "lib" folder, as it is no longer used for loading local JNDI overrides. Of course "CayenneModeler-the-app" is still included.</p> </li>
<li> <p>Ashwood library used for commit operation sorting is no longer a third-party dependency. Instead a small subset of the relevant Ashwood classes got included in Cayenne core.</p> </li>
<li> <p>The following helper modules are split away from Cayenne core: "cayenne-project" and "cayenne-wocompat". They are bundled in CayenneModeler, and are available from the source distribution. They are not included as standalone jars in the binary distribution.</p> </li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="cayenne-configuration"><a class="anchor" href="#cayenne-configuration"></a>1.2. Cayenne Configuration</h3>
<div class="admonitionblock note">
<table>
<tbody>
<tr>
<td class="icon"> <i class="fa fa-info-circle fa-2x" title="Note"></i> </td>
<td class="content"> The new DI-based bootstrap and configuration approach is not API-compatible with earlier versions of Cayenne. Make sure you read the <code>UPGRADE.txt</code> file for instructions how to upgrade the existing projects. </td>
</tr>
</tbody>
</table>
</div>
<div class="sect3">
<h4 id="dependency-injection-container"><a class="anchor" href="#dependency-injection-container"></a>Dependency Injection Container</h4>
<div class="paragraph">
<p>Cayenne 3.1 runtime stack is built around the ideas of Dependency Injection (DI), making it extremely flexible and easy to extend. It bundles a small, flexible annotations-based DI container to configure its services. The container provides DI services and exposes Cayenne extension points, but does not interfere with other DI containers that may be present in the application. I.e. it is invisible to the users who do not care about advanced Cayenne customization.</p>
</div>
</div>
<div class="sect3">
<h4 id="bootstrapping-cayenne-in-various-environments"><a class="anchor" href="#bootstrapping-cayenne-in-various-environments"></a>Bootstrapping Cayenne in Various Environments</h4>
<div class="paragraph">
<p>Here is a simple example of starting a server-side Cayenne stack:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">ServerRuntime runtime = new ServerRuntime("cayenne-UntitledDomain.xml");</code></pre>
</div>
</div>
<div class="paragraph">
<p>For more detailed examples check the tutorials and other documentation.</p>
</div>
</div>
<div class="sect3">
<h4 id="configuring-local-datasources-removal-of-jndi-hack"><a class="anchor" href="#configuring-local-datasources-removal-of-jndi-hack"></a>Configuring Local DataSources, Removal of JNDI Hack</h4>
<div class="paragraph">
<p>Cayenne 3.1 provides a property-based mechanism to override Modeler DataSource definitions, regardless of whether they are driver configurations, JNDI, DBCP, etc. A quick configuration example is shown below:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code>-Dcayenne.jdbc.driver=com.mysql.jdbc.Driver -Dcayenne.jdbc.url=jdbc:mysql://localhost/mydb \
-Dcayenne.jdbc.username=user -Dcayenne.jdbc.password=password</code></pre>
</div>
</div>
<div class="paragraph">
<p>For more details and configuration options see javadocs of <code>org.apache.cayenne.configuration.server.PropertyDataSourceFactory</code>.</p>
</div>
<div class="paragraph">
<p>This feature supersedes what was formerly known as "JNDI hack", i.e. JNDI DataSource failover load strategy based on CayenneModeler preferences database. The problem with JNDI hack was unstable and frequently corrupted preferences database, and the need to include hsqldb and cayenne-modeler jars in the runtime.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="framework-api"><a class="anchor" href="#framework-api"></a>1.3. Framework API</h3>
<div class="paragraph">
<p>See UPGRADE.txt for the full list of changes</p>
</div>
<div class="sect3">
<h4 id="lifecycle-listener-annotations"><a class="anchor" href="#lifecycle-listener-annotations"></a>Lifecycle Listener Annotations</h4>
<div class="paragraph">
<p>Cayenne 3.1 features support for annotations on lifecycle listeners (but not yet on entity callback methods) that simplifies registering listeners via API. Our experience with Cayenne 3.0 shows that mapping listeners in the Modeler doesn’t scale well to complex applications, and 3.0 API for mapping the listeners is hard to use. In 3.1 you can annotate listener methods and register multiple callback methods with a single call.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">// declare a listener with annotated methods
class MyListener {
@PostLoad(Entity1.class)
@PostPersist(Entity1.class)
void postLoad(Object object) {
....
}
}
// register a listener
ServerRuntime runtime = ..
MyListener listener = new MyListener();
runtime.getChannel().getEntityResolver().getCallbackRegistry().addListener(listener);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Moreover, unlike JPA annotations, Cayenne allows to attach a listener to a set of entities not known to the listener upfront, but that are all annotated with some custom annotation:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">class MyListener {
@PostLoad(entityAnnotations = CustomAnnotation.class)
void postLoad(Object object) {
....
}
}</code></pre>
</div>
</div>
</div>
<div class="sect3">
<h4 id="datachannelfilter-for-intercepting-datadomain-operations"><a class="anchor" href="#datachannelfilter-for-intercepting-datadomain-operations"></a>DataChannelFilter for Intercepting DataDomain Operations</h4>
<div class="paragraph">
<p>Cayenne now features a DataChannelFilter interface that allows to intercept and alter all DataChannel traffic (i.e. selects and commits between a DataContext and DataDomain). It provides a chain of command API very similar to servlet filters. Filters are widely used by "cayenne-lifecyle" extensions and allow to build powerful custom object lifecycle-aware code. To install a filter, the following API is used:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">class MyFilter implement DataChannelFilter { .. }
MyFilter filter = new MyFilter();
ServerRuntime runtime = ..
runtime.getDataDomain().addFilter(filter);</code></pre>
</div>
</div>
<div class="paragraph">
<p>Very often filters mark some of their own methods with lifecycle annotations so that certain operations can be triggered by Cayenne inside the scope of filter’s onQuery() or onSync() methods. To ensure annotated methods are invoked, filter registration should be combined with listener registration:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-java java" data-lang="java">MyFilter filter = new MyFilter();
ServerRuntime runtime = ..
runtime.getDataDomain().addFilter(filter);
runtime.getDataDomain().getEntityResolver().getCallbackRegistry().addListener(filter);
// noticed that by default runtime.getDataDomain() is equivalent to runtime.getChannel()</code></pre>
</div>
</div>
</div>
</div>
<div class="sect2">
<h3 id="cayennemodeler"><a class="anchor" href="#cayennemodeler"></a>1.4. CayenneModeler</h3>
<div class="sect3">
<h4 id="java-preferences-api"><a class="anchor" href="#java-preferences-api"></a>Java Preferences API</h4>
<div class="paragraph">
<p>We got rid of HSQLDB-based preferences storage, and are using standard Java Preferences API for the Modeler preferences. This solved a long-standing stability issue with Modeler preferences. So no more lost user preferences.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="lifecycle-extensions"><a class="anchor" href="#lifecycle-extensions"></a>1.5. Lifecycle Extensions</h3>
<div class="paragraph">
<p>Cayenne 3.1 includes an optional cayenne-lifecyle module that implements a few useful extensions based on DataChannelFilters and lifecycle annotations. Those include a concept of a String ID (which is a String URL-friendly representation of ObjectId), support for (de)referencing objects by String ID, String ID-based relationships, annotation-based cache groups invalidation, annotation-based audit of object changes, etc.</p>
</div>
</div>
</div>
</div>
</section>
<footer>
<div class="row">
<div class="col-6 col-md-3 text-center text-md-left">
&nbsp;
</div>
<div class="col-18 col-md-9 text-center text-md-right">
</div>
</div>
</footer>
</article>
<img referrerpolicy="no-referrer-when-downgrade" src="https://static.scarf.sh/a.png?x-pxid=5c836e39-be6b-4a21-a946-a97b5b69f172" />
</div>
</div>
</div>
</main>
<footer class="bg-dark">
<div class="footer-nav container text-center text-lg-left pb-3">
<div class="row pt-5 pb-3">
<div class="col-sm-6 col-lg-3">
<h4>About</h4>
<ul class="list-unstyled">
<li>
<a href="/why-cayenne.html">Why Cayenne?</a>
</li>
<li>
<a href="/download/">Download</a>
</li>
<li>
<a href="/success-stories.html">Success Stories</a>
</li>
<li>
<a href="/about/support/">Support</a>
</li>
</ul>
</div>
<div class="col-sm-6 col-lg-3">
<h4>Documentation</h4>
<ul class="list-unstyled">
<li>
<a href="/docs/4.0/getting-started-guide/">Getting Started (4.0)</a>
</li>
<li>
<a href="/docs/4.1/getting-started-guide/">Getting Started (4.1)</a>
</li>
<li>
<a href="/docs/4.2/getting-started-guide/">Getting Started (4.2)</a>
</li>
<li>
<a href="/docs/4.0/cayenne-guide/">Cayenne Guide (4.0)</a>
</li>
<li>
<a href="/docs/4.1/cayenne-guide/">Cayenne Guide (4.1)</a>
</li>
<li>
<a href="/docs/4.2/cayenne-guide/">Cayenne Guide (4.2)</a>
</li>
<li>
<a href="/docs/4.1/getting-started-db-first/">Database First tutorial (4.1)</a>
</li>
<li>
<a href="/docs/4.2/getting-started-db-first/">Database First tutorial (4.2)</a>
</li>
<li>
<a href="/legacy/legacy-docs/">Legacy Documentation</a>
</li>
</ul>
</div>
<div class="col-sm-6 col-lg-3">
<h4>Collaboration</h4>
<ul class="list-unstyled">
<li>
<a href="https://issues.apache.org/jira/browse/CAY">Bug/Feature Tracker</a>
</li>
<li>
<a href="/mailing-lists.html">Mailing Lists</a>
</li>
<li>
<a href="/dev/code-repository.html">Code Repository</a>
</li>
<li>
<a href="/dev/">Developer Guide</a>
</li>
<li>
<a href="/how-can-i-help.html">How can I help?</a>
</li>
<li>
<a href="/contributors.html">Contributors</a>
</li>
<li>
<a href="/thanks.html">Thanks</a>
</li>
</ul>
</div>
<div class="col-sm-6 col-lg-3">
<h4>News</h4>
<ul class="list-multiline-items list-unstyled mb-0">
<li>
<time datetime="2023-05-25 18:00:00 &#43;0300 &#43;0300" class="xsmall d-block">May 25, 2023</time>
<a href="/2023/05/cayenne-42-final-released/">Cayenne 4.2 Final Released</a>
</li>
<li>
<time datetime="2023-03-02 12:00:00 &#43;0300 &#43;0300" class="xsmall d-block">Mar 02, 2023</time>
<a href="/2023/03/cayenne-403-released/">Cayenne 4.0.3 Released</a>
</li>
<li>
<time datetime="2022-12-05 12:00:00 &#43;0300 &#43;0300" class="xsmall d-block">Dec 05, 2022</time>
<a href="/2022/12/cayenne-42rc2-released/">Cayenne 4.2 Release Candidate 2 Released</a>
</li>
</ul>
<a class="btn-link text-uppercase xsmall" href="https://cayenne.apache.org/news">
More news
<i class="fa fa-lg fa-long-arrow-right" aria-hidden="true"></i>
</a>
</div>
</div>
<hr class="mt-0 mb-3" />
<p class="copy xsmall text-center mw-75 mx-auto mb-0">
Copyright © 2001-2024 Apache Software Foundation. Apache Cayenne, Cayenne, Apache, the Apache feather logo, and the Apache Cayenne project logo are trademarks of The Apache Software Foundation.
<a href="https://privacy.apache.org/policies/privacy-policy-public.html">Privacy policy</a>.
<img class="d-block mx-auto mt-2" src="/img/logo_mono-3302daa3cf.svg" alt="Apache Cayenne" />
</p>
</div>
</footer>
</body>
</html>