You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2018/01/05 14:21:33 UTC

[05/11] cayenne git commit: CAY-2371 Switch documentation from Docbook to Asciidoctor format

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/docbook/cayenne-guide/src/docbkx/lifecycle-events.xml
----------------------------------------------------------------------
diff --git a/docs/docbook/cayenne-guide/src/docbkx/lifecycle-events.xml b/docs/docbook/cayenne-guide/src/docbkx/lifecycle-events.xml
deleted file mode 100644
index 364b5da..0000000
--- a/docs/docbook/cayenne-guide/src/docbkx/lifecycle-events.xml
+++ /dev/null
@@ -1,333 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements. See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to you under the Apache License, Version
-    2.0 (the "License"); you may not use this file except in compliance
-    with the License. You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0 Unless required by
-    applicable law or agreed to in writing, software distributed under the
-    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-    CONDITIONS OF ANY KIND, either express or implied. See the License for
-    the specific language governing permissions and limitations under the
-    License.
--->
-<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
-    version="5.0" xml:id="lifecycle-events">
-    <title>Lifecycle Events</title>
-    <para>An application might be interested in getting notified when a Persistent object moves
-        through its lifecycle (i.e. fetched from DB, created, modified, committed). E.g. when a new
-        object is created, the application may want to initialize its default properties (this can't
-        be done in constructor, as constructor is also called when an object is fetched from DB).
-        Before save, the application may perform validation and/or set some properties (e.g.
-        "updatedTimestamp"). After save it may want to create an audit record for each saved object,
-        etc., etc. </para>
-    <para>All this can be achieved by declaring callback methods either in Persistent objects or in
-        non-persistent listener classes defined by the application (further simply called
-        "listeners"). There are eight types of lifecycle events supported by Cayenne, listed later
-        in this chapter. When any such event occurs (e.g. an object is committed), Cayenne would
-        invoke all appropriate callbacks. Persistent objects would receive their own events, while
-        listeners would receive events from any objects. </para>
-    <para>Cayenne allows to build rather powerful and complex "workflows" or "processors" tied to
-        objects lifecycle, especially with listeners, as they have full access to the application
-        evnironment outside Cayenne. This power comes from such features as filtering which entity
-        events are sent to a given listener and the ability to create a common operation context for
-        multiple callback invocations. All of these are discussed later in this chapter.</para>
-    <section xml:id="types-of-lifecycle-events">
-        <title>Types of Lifecycle Events</title>
-        <para>Cayenne defines the following 8 types of lifecycle events for which callbacks can be
-                regsitered:<table frame="void">
-                <caption>Lifecycle Event Types</caption>
-                <col width="16%"/>
-                <col width="84%"/>
-                <thead>
-                    <tr>
-                        <th>Event</th>
-                        <th>Occurs...</th>
-                    </tr>
-                </thead>
-                <tbody>
-                    <tr>
-                        <td>PostAdd</td>
-                        <td>right after a new object is created inside
-                                <code>ObjectContext.newObject()</code>. When this event is fired the
-                            object is already registered with its ObjectContext and has its ObjectId
-                            and ObjectContext properties set.</td>
-                    </tr>
-                    <tr>
-                        <td>PrePersist</td>
-                        <td>right before a new object is committed, inside
-                                <code>ObjectContext.commitChanges()</code> and
-                                <code>ObjectContext.commitChangesToParent()</code> (and prior to
-                                "<code>validateForInsert()</code>").</td>
-                    </tr>
-                    <tr>
-                        <td>PreUpdate</td>
-                        <td>right before a modified object is committed, inside
-                                <code>ObjectContext.commitChanges()</code> and
-                                <code>ObjectContext.commitChangesToParent()</code> (and prior to
-                                "<code>validateForUpdate()</code>").</td>
-                    </tr>
-                    <tr>
-                        <td>PreRemove</td>
-                        <td>right before an object is deleted, inside
-                                <code>ObjectContext.deleteObjects()</code>. The event is also
-                            generated for each object indirectly deleted as a result of CASCADE
-                            delete rule.</td>
-                    </tr>
-                    <tr>
-                        <td>PostPersist</td>
-                        <td>right after a commit of a new object is done, inside
-                                <code>ObjectContext.commitChanges()</code>.</td>
-                    </tr>
-                    <tr>
-                        <td>PostUpdate</td>
-                        <td>right after a commit of a modified object is done, inside
-                                <code>ObjectContext.commitChanges()</code>.</td>
-                    </tr>
-                    <tr>
-                        <td>PostRemove</td>
-                        <td>right after a commit of a deleted object is done, inside
-                                <code>ObjectContext.commitChanges()</code>.</td>
-                    </tr>
-                    <tr>
-                        <td>PostLoad</td>
-                        <td>
-                            <itemizedlist>
-                                <listitem>
-                                    <para>After an object is fetched inside
-                                            <code>ObjectContext.performQuery()</code>.</para>
-                                </listitem>
-                                <listitem>
-                                    <para>After an object is reverted inside
-                                            <code>ObjectContext.rollbackChanges()</code>.</para>
-                                </listitem>
-                                <listitem>
-                                    <para>Anytime a faulted object is resolved (i.e. if a
-                                        relationship is fetched).</para>
-                                </listitem>
-                            </itemizedlist>
-                        </td>
-                    </tr>
-                </tbody>
-            </table></para>
-    </section>
-    <section xml:id="callback-persistent">
-        <title>Callbacks on Persistent Objects</title>
-        <para>Callback methods on Persistent classes are mapped in CayenneModeler for each
-            ObjEntity. Empty callback methods are automatically created as a part of class
-            generation (either with Maven, Ant or the Modeler) and are later filled with appropriate
-            logic by the programmer. E.g. assuming we mapped a 'post-add' callback called
-            'onNewOrder' in ObjEntity 'Order', the following code will be
-            generated:<programlisting language="java">public abstract class _Order extends CayenneDataObject {
-    protected abstract void onNewOrder();
-}
-
-public class Order extends _Order {
-
-    @Override
-    protected void onNewOrder() {
-        //TODO: implement onNewOrder
-    }
-}</programlisting></para>
-        <para>As <code>onNewOrder()</code> is already declared in the mapping, it does not need to
-            be registered explicitly. Implementing the method in subclass to do something meaningful
-            is all that is required at this point. </para>
-        <para>As a rule callback methods do not have any knowledge of the outside application, and
-            can only access the state of the object itself and possibly the state of other
-            persistent objects via object's own ObjectContext.</para>
-        <para>
-            <note>
-                <para><emphasis role="italic">Validation and callbacks:</emphasis> There is a clear
-                    overlap in functionality between object callbacks and
-                        <code>DataObject.validateForX()</code> methods. In the future validation may
-                    be completely superceeded by callbacks. It is a good idea to use "validateForX"
-                    strictly for validation (or not use it at all). Updating the state before commit
-                    should be done via callbacks.</para>
-            </note>
-        </para>
-    </section>
-    <section xml:id="callback-non-persistent">
-        <title>Callbacks on Non-Persistent Listeners</title>
-        
-            <para>
-                <note>
-                    <para>While listener callback methods can be declared in the Modeler (at least
-                        as of this wrting), which ensures their automatic registration in runtime,
-                        there's a big downside to it. The power of the listeners lies in their
-                        complete separation from the XML mapping. The mapping once created, can be
-                        reused in different contexts each having a different set of listeners.
-                        Placing a Java class of the listener in the XML mapping, and relying on
-                        Cayenne to instantiate the listeners severly limits mapping reusability.
-                        Further down in this chapter we'll assume that the listener classes are
-                        never present in the DataMap and are registered via API.</para>
-                </note>
-            </para>
-            <para>A listener is simply some application class that has one or more annotated
-            callback methods. A callback method signature should be <code>void
-                someMethod(SomePersistentType object)</code>. It can be public, private, protected
-            or use default access:</para>
-            <para>
-                <programlisting language="java"> public class OrderListener { 
-  
-   @PostAdd(Order.class)
-   public void setDefaultsForNewOrder(Order o) {
-      o.setCreatedOn(new Date());
-   }
-}</programlisting>
-            </para>
-        <para>Notice that the example above contains an annotation on the callback method that
-            defines the type of the event this method should be called for. Before we go into
-            annotation details, we'll show how to create and register a listener with Cayenne. It is
-            always a user responsibility to register desired application listeners, usually right
-            after ServerRuntime is started. Here is an example:</para>
-        <para>First let's define 2 simple
-            listeners.<programlisting language="java">public class Listener1 {
-
-    @PostAdd(MyEntity.class)
-    void postAdd(Persistent object) {
-        // do something
-    }
-}
-
-public class Listener2 {
-
-    @PostRemove({ MyEntity1.class, MyEntity2.class })
-    void postRemove(Persistent object) {
-        // do something
-    }
-
-    @PostUpdate({ MyEntity1.class, MyEntity2.class })
-    void postUpdate(Persistent object) {
-        // do something
-    }
-}</programlisting></para>
-        <para>Ignore the annotations for a minute. The important point here is that the listeners
-            are arbitrary classes unmapped and unknown to Cayenne, that contain some callback
-            methods. Now let's register them with
-            runtime:<programlisting language="java">ServerRuntime runtime = ...
-
-LifecycleCallbackRegistry registry = 
-    runtime.getDataDomain().getEntityResolver().getCallbackRegistry();
-
-registry.addListener(new Listener1());
-registry.addListener(new Listener2());</programlisting></para>
-        <para>Listeners in this example are very simple. However they don't have to be. Unlike
-            Persistent objects, normally listeners initialization is managed by the application
-            code, not Cayenne, so listeners may have knowledge of various application services,
-            operation transactional context, etc. Besides a single listener can apply to multiple
-            entities. As a consequence their callbacks can do more than just access a single
-            ObjectContext. </para>
-        <para>Now let's discuss the annotations. There are eight annotations exactly matching the
-            names of eight lifecycle events. A callback method in a listener should be annotated
-            with at least one, but possibly with more than one of them. Annotation itself defines
-            what event the callback should react to. Annotation parameters are essentially an entity
-            filter, defining a subset of ObjEntities whose events we are interested
-            in:<programlisting language="java">// this callback will be invoked on PostRemove event of any object 
-// belonging to MyEntity1, MyEntity2 or their subclasses
-@PostRemove({ MyEntity1.class, MyEntity2.class })
-void postRemove(Persistent object) {
-    ...
-}</programlisting><programlisting language="java">// similar example with multipe annotations on a single method
-// each matching just one entity
-@PostPersist(MyEntity1.class)
-@PostRemove(MyEntity1.class)
-@PostUpdate(MyEntity1.class)
-void postCommit(MyEntity1 object) {
-    ...
-}</programlisting></para>
-        <para>As shown above, "value" (the implicit annotation parameter) can contain one or more
-            entity classes. Only these entities' events will result in callback invocation. There's
-            also another way to match entities - via custom annotations. This allows to match any
-            number of entities without even knowing what they are. Here is an example. We'll first
-            define a custom
-            annotation:<programlisting language="java">@Target(ElementType.TYPE)
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Tag {
-
-}</programlisting></para>
-        <para>Now we can define a listener that will react to events from ObjEntities annotated with
-            this
-            annotation:<programlisting language="java">public class Listener3 {
-
-    @PostAdd(entityAnnotations = Tag.class)
-    void postAdd(Persistent object) {
-        // do something
-    }
-}</programlisting></para>
-        <para>As you see we don't have any entities yet, still we can define a listener that does
-            something useful. Now let's annotate some
-            entities:<programlisting language="java">@Tag
-public class MyEntity1 extends _MyEntity1 {
-
-}
-
-@Tag
-public class MyEntity2 extends _MyEntity2 {
-
-}</programlisting></para>
-        </section>
-
-    <section xml:id="comining-listeners-with-datachannelfilters">
-        <title>Combining Listeners with DataChannelFilters</title>
-        <para>A final touch in the listeners design is preserving the state of the listener within a
-            single select or commit, so that events generated by multiple objects can be collected
-            and processed all together. To do that you will need to implement a
-                <code>DataChannelFilter</code>, and add some callback methods to it. They will store
-            their state in a ThreadLocal variable of the filter. Here is an example filter that does
-            something pretty meaningless - counts how many total objects were committed. However it
-            demonstrates the important pattern of aggregating multiple events and presenting a
-            combined
-            result:<programlisting language="java">public class CommittedObjectCounter implements DataChannelFilter {
-
-    private ThreadLocal&lt;int[]> counter;
-
-    @Override
-    public void init(DataChannel channel) {
-        counter = new ThreadLocal&lt;int[]>();
-    }
-
-    @Override
-    public QueryResponse onQuery(ObjectContext originatingContext, Query query, DataChannelFilterChain filterChain) {
-        return filterChain.onQuery(originatingContext, query);
-    }
-
-    @Override
-    public GraphDiff onSync(ObjectContext originatingContext, GraphDiff changes, int syncType,
-            DataChannelFilterChain filterChain) {
-        
-        // init the counter for the current commit
-        counter.set(new int[1]);
-
-        try {
-            return filterChain.onSync(originatingContext, changes, syncType);
-        } finally {
-
-            // process aggregated result and release the counter
-            System.out.println("Committed " + counter.get()[0] + " object(s)");
-            counter.set(null);
-        }
-    }
-
-    @PostPersist(entityAnnotations = Tag.class)
-    @PostUpdate(entityAnnotations = Tag.class)
-    @PostRemove(entityAnnotations = Tag.class)
-    void afterCommit(Persistent object) {
-        counter.get()[0]++;
-    }
-}</programlisting></para>
-        <para>Now since this is both a filter and a listener, it needs to be registered as
-            such:<programlisting language="java">CommittedObjectCounter counter = new CommittedObjectCounter();
-
-ServerRuntime runtime = ...
-DataDomain domain = runtime.getDataDomain();
-
-// register filter
-domain.addFilter(counter);
-
-// register listener
-domain.getEntityResolver().getCallbackRegistry().addListener(counter);</programlisting></para>
-    </section>
-</chapter>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/docbook/cayenne-guide/src/docbkx/orderings.xml
----------------------------------------------------------------------
diff --git a/docs/docbook/cayenne-guide/src/docbkx/orderings.xml b/docs/docbook/cayenne-guide/src/docbkx/orderings.xml
deleted file mode 100644
index f1b9c0e..0000000
--- a/docs/docbook/cayenne-guide/src/docbkx/orderings.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements. See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to you under the Apache License, Version
-    2.0 (the "License"); you may not use this file except in compliance
-    with the License. You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0 Unless required by
-    applicable law or agreed to in writing, software distributed under the
-    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-    CONDITIONS OF ANY KIND, either express or implied. See the License for
-    the specific language governing permissions and limitations under the
-    License.
--->
-<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
-    version="5.0" xml:id="orderings">
-    <title>Orderings</title>
-        <para>An Ordering object defines how a list of objects should be ordered. Orderings are
-            essentially path expressions combined with a sorting strategy. Creating an Ordering:
-            <programlisting language="java">Ordering o = new Ordering(Painting.NAME_PROPERTY, SortOrder.ASENDING);</programlisting></para>
-        <para>Like expressions, orderings are translated into SQL as parts of queries (and the sorting
-        occurs in the database). Also like expressions, orderings can be used in memory, naturally -
-        to sort
-        objects:<programlisting language="java">Ordering o = new Ordering(Painting.NAME_PROPERTY, SortOrder.ASCENDING_INSENSITIVE);
-List&lt;Painting> list = ...
-o.orderList(list);</programlisting>Note
-        that unlike filtering with Expressions, ordering is performed in-place. This list object is
-        reordered and no new list is created.</para>
-</chapter>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/docbook/cayenne-guide/src/docbkx/part1.xml
----------------------------------------------------------------------
diff --git a/docs/docbook/cayenne-guide/src/docbkx/part1.xml b/docs/docbook/cayenne-guide/src/docbkx/part1.xml
deleted file mode 100644
index ac79499..0000000
--- a/docs/docbook/cayenne-guide/src/docbkx/part1.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-	Licensed to the Apache Software Foundation (ASF) under one or more
-	contributor license agreements. See the NOTICE file distributed with
-	this work for additional information regarding copyright ownership.
-	The ASF licenses this file to you under the Apache License, Version
-	2.0 (the "License"); you may not use this file except in compliance
-	with the License. You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0 Unless required by
-	applicable law or agreed to in writing, software distributed under the
-	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-	CONDITIONS OF ANY KIND, either express or implied. See the License for
-	the specific language governing permissions and limitations under the
-	License.
--->
-<part xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
-        xml:id="cayenne-guide-part1" xmlns:xi="http://www.w3.org/2001/XInclude">
-        <title>Object Relational Mapping with Cayenne</title>
-        <xi:include href="setup.xml"/>
-        <xi:include href="cayenne-mapping-structure.xml"/>
-        <xi:include href="cayennemodeler-application.xml"/>
-</part>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/docbook/cayenne-guide/src/docbkx/part2.xml
----------------------------------------------------------------------
diff --git a/docs/docbook/cayenne-guide/src/docbkx/part2.xml b/docs/docbook/cayenne-guide/src/docbkx/part2.xml
deleted file mode 100644
index c5f8201..0000000
--- a/docs/docbook/cayenne-guide/src/docbkx/part2.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements. See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to you under the Apache License, Version
-    2.0 (the "License"); you may not use this file except in compliance
-    with the License. You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0 Unless required by
-    applicable law or agreed to in writing, software distributed under the
-    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-    CONDITIONS OF ANY KIND, either express or implied. See the License for
-    the specific language governing permissions and limitations under the
-    License.
--->
-<part xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
-    xml:id="cayenne-guide-part2" xmlns:xi="http://www.w3.org/2001/XInclude">
-    <title>Cayenne Framework</title>
-    <xi:include href="including-cayenne-in-project.xml"/>
-    <xi:include href="starting-cayenne.xml"/>
-    <xi:include href="persistent-objects-objectcontext.xml"/>
-    <xi:include href="expressions.xml"/>
-    <xi:include href="orderings.xml"/>
-    <xi:include href="queries.xml"/>
-    <xi:include href="lifecycle-events.xml"/>
-    <xi:include href="performance-tuning.xml"/>
-    <xi:include href="customizing-cayenne-runtime.xml"/>
-</part>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/docbook/cayenne-guide/src/docbkx/part3.xml
----------------------------------------------------------------------
diff --git a/docs/docbook/cayenne-guide/src/docbkx/part3.xml b/docs/docbook/cayenne-guide/src/docbkx/part3.xml
deleted file mode 100644
index 75c60b3..0000000
--- a/docs/docbook/cayenne-guide/src/docbkx/part3.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-	Licensed to the Apache Software Foundation (ASF) under one or more
-	contributor license agreements. See the NOTICE file distributed with
-	this work for additional information regarding copyright ownership.
-	The ASF licenses this file to you under the Apache License, Version
-	2.0 (the "License"); you may not use this file except in compliance
-	with the License. You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0 Unless required by
-	applicable law or agreed to in writing, software distributed under the
-	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-	CONDITIONS OF ANY KIND, either express or implied. See the License for
-	the specific language governing permissions and limitations under the
-	License.
--->
-<part xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0"
-    xml:id="cayenne-guide-part3" xmlns:xi="http://www.w3.org/2001/XInclude">
-    <title>Cayenne Framework - Remote Object Persistence </title>
-    <xi:include href="rop-introduction.xml"/>
-    <xi:include href="rop-setup.xml"/>
-    <xi:include href="implementing-rop-server.xml"/>
-    <xi:include href="implementing-rop-client.xml"/>
-    <xi:include href="rop-deployment.xml"/>
-    <xi:include href="current-limitations.xml"/>
-</part>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/docbook/cayenne-guide/src/docbkx/performance-tuning.xml
----------------------------------------------------------------------
diff --git a/docs/docbook/cayenne-guide/src/docbkx/performance-tuning.xml b/docs/docbook/cayenne-guide/src/docbkx/performance-tuning.xml
deleted file mode 100644
index 18bb0bc..0000000
--- a/docs/docbook/cayenne-guide/src/docbkx/performance-tuning.xml
+++ /dev/null
@@ -1,289 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements. See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to you under the Apache License, Version
-    2.0 (the "License"); you may not use this file except in compliance
-    with the License. You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0 Unless required by
-    applicable law or agreed to in writing, software distributed under the
-    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-    CONDITIONS OF ANY KIND, either express or implied. See the License for
-    the specific language governing permissions and limitations under the
-    License.
--->
-<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
-    version="5.0" xml:id="performance-tuning">
-    <title>Performance Tuning</title>
-    <section xml:id="prefetching">
-        <title>Prefetching</title>
-        <para>Prefetching is a technique that allows to bring back in one query not only the queried
-            objects, but also objects related to them. In other words it is a controlled eager
-            relationship resolving mechanism. Prefetching is discussed in the "Performance Tuning"
-            chapter, as it is a powerful performance optimization method. However another common
-            application of prefetching is to refresh stale object relationships, so more generally
-            it can be viewed as a technique for managing subsets of the object graph.</para>
-        <para>Prefetching example:
-            <programlisting language="java">SelectQuery query = new SelectQuery(Artist.class);
-
-// this instructs Cayenne to prefetch one of Artist's relationships
-query.addPrefetch("paintings");
-
-// query is expecuted as usual, but the resulting Artists will have
-// their paintings "inflated"
-List&lt;Artist> artists = context.performQuery(query);</programlisting>All
-            types of relationships can be preftetched - to-one, to-many, flattened. </para>
-        <para>A prefetch can span multiple relationships:
-            <programlisting language="java"> query.addPrefetch("paintings.gallery");</programlisting></para>
-        <para>A query can have multiple
-            prefetches:<programlisting language="java">query.addPrefetch("paintings");
-query.addPrefetch("paintings.gallery"); </programlisting></para>
-        <para>If a query is fetching DataRows, all "disjoint" prefetches are ignored, only "joint"
-            prefetches are executed (see prefetching semantics discussion below for what disjoint and
-            joint prefetches mean).</para>
-
-        <section xml:id="prefetching-semantics">
-            <title>Prefetching Semantics</title>
-            <para>Prefetching semantics defines a strategy to prefetch relationships. Depending on
-                it, Cayenne would generate different types of queries. The end result is the same -
-                query root objects with related objects fully resolved. However semantics can affect
-                preformance, in some cases significantly. There are 3 types of prefetch semantics,
-                all defined as constants in
-                org.apache.cayenne.query.PrefetchTreeNode:<programlisting language="java">PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS
-PrefetchTreeNode.DISJOINT_PREFETCH_SEMANTICS
-PrefetchTreeNode.DISJOINT_BY_ID_PREFETCH_SEMANTICS</programlisting></para>
-            <para>Each query has a default prefetch semantics, so generally users do not have to
-                worry about changing it, except when performance is a concern, or a few special
-                cases when a default sematics can't produce the correct result. SelectQuery uses
-                DISJOINT_PREFETCH_SEMANTICS by default. Semantics can be changed as
-                follows:<programlisting language="java">SelectQuery query = new SelectQuery(Artist.class);
-query.addPrefetch("paintings").setSemantics(
-                PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS); </programlisting></para>
-            <para>There's no limitation on mixing different types of semantics in the same
-                SelectQuery. Multiple prefetches each can have its own semantics. </para>
-            <para>SQLTemplate and ProcedureQuery are both using JOINT_PREFETCH_SEMANTICS and it can
-                not be changed due to the nature of these two queries.</para>
-        </section>
-        <section xml:id="disjoint-prefetch-semantics">
-            <title>Disjoint Prefetching Semantics</title>
-            <para>This semantics (only applicable to SelectQuery) results in Cayenne generatiing one
-                SQL statement for the main objects, and a separate statement for each prefetch path
-                (hence "disjoint" - related objects are not fetched with the main query). Each
-                additional SQL statement uses a qualifier of the main query plus a set of joins
-                traversing the preftech path between the main and related entity. </para>
-            <para>This strategy has an advantage of efficient JVM memory use, and faster overall
-                result processing by Cayenne, but it requires (1+N) SQL statements to be executed,
-                where N is the number of prefetched relationships.</para>
-
-        </section>
-        <section xml:id="disjoint-by-id-prefetch-semantics">
-            <title>Disjoint-by-ID Prefetching Semantics</title>
-            <para>This is a variation of disjoint prefetch where related objects are matched against
-                a set of IDs derived from the fetched main objects (or intermediate objects in a
-                multi-step prefetch). Cayenne limits the size of the generated WHERE clause, as most
-                DBs can't parse arbitrary large SQL. So prefetch queries are broken into smaller
-                queries. The size of  is controlled by the DI property
-                Constants.SERVER_MAX_ID_QUALIFIER_SIZE_PROPERTY (the default number of conditions in
-                the generated WHERE clause is 10000). Cayenne will generate (1 + N * M) SQL
-                statements for each query using disjoint-by-ID prefetches, where N is the number of
-                relationships to prefetch, and M is the number of queries for a given prefetch that
-                is dependent on the number of objects in the result (ideally M = 1).</para>
-            <para>The advantage of this type of prefetch is that matching database rows by ID may be
-                much faster than matching the qualifier of the original query. Moreover this is
-                    <emphasis role="bold">the only type of prefetch</emphasis> that can handle
-                SelectQueries with <emphasis role="bold">fetch limit</emphasis>. Both joint and
-                regular disjoint prefetches may produce invalid results or generate inefficient
-                fetch-the-entire table SQL when fetch limit is in effect. </para>
-            <para>The disadvantage is that query SQL can get unwieldy for large result sets, as each
-                object will have to have its own condition in the WHERE clause of the generated
-                SQL.</para>
-        </section>
-        <section xml:id="joint-prefetch-semantics">
-            <title>Joint Prefetching Semantics</title>
-            <para>Joint semantics results in a single SQL statement for root objects and any number
-                of jointly prefetched paths. Cayenne processes in memory a cartesian product of the
-                entities involved, converting it to an object tree. It uses OUTER joins to connect
-                prefetched entities.</para>
-            <para>Joint is the most efficient prefetch type of the three as far as generated SQL
-                goes. There's always just 1 SQL query generated. Its downsides are the potentially
-                increased amount of data that needs to get across the network between the
-                application server and the database, and more data processing that needs to be done
-                on the Cayenne side.</para>
-        </section>
-    </section>
-    <section xml:id="datarows">
-        <title>Data Rows</title>
-        <para>Converting result set data to Persistent objects and registering these objects in the
-            ObjectContext can be an expensive operation compareable to the time spent running the
-            query (and frequently exceeding it). Internally Cayenne builds the result as a list of
-            DataRows, that are later converted to objects. Skipping the last step and using data in
-            the form of DataRows can significantly increase performance. </para>
-        <para>DataRow is a simply a map of values keyed by their DB column name. It is a ubiqutous
-            representation of DB data used internally by Cayenne. And it can be quite usable as is
-            in the application in many cases. So performance sensitive selects should consider
-            DataRows - it saves memory and CPU cycles. All selecting queries support DataRows
-            option,
-            e.g.:<programlisting language="java">SelectQuery query = new SelectQuery(Artist.class);
-query.setFetchingDataRows(true);
-
-List&lt;DataRow> rows = context.performQuery(query); </programlisting><programlisting language="java">SQLTemplate query = new SQLTemplate(Artist.class, "SELECT * FROM ARTIST");
-query.setFetchingDataRows(true);
-
-List&lt;DataRow> rows = context.performQuery(query);</programlisting></para>
-        <para>Moreover DataRows may be converted to Persistent objects later as needed. So e.g. you
-            may implement some in-memory filtering, only converting a subset of fetched
-            objects:<programlisting language="java">// you need to cast ObjectContext to DataContext to get access to 'objectFromDataRow'
-DataContext dataContext = (DataContext) context;
-
-for(DataRow row : rows) {
-    if(row.get("DATE_OF_BIRTH") != null) {
-        Artist artist = dataContext.objectFromDataRow(Artist.class, row);
-        // do something with Artist...
-        ...
-    }
-}</programlisting></para>
-    </section>
-    <section xml:id="iterated-queries">
-        <title>Iterated Queries</title>
-        <para>While contemporary hardware may easily allow applications to fetch hundreds of
-            thousands or even millions of objects into memory, it doesn't mean this is always a good
-            idea to do so. You can optimize processing of very large result sets with two techniques
-            discussed in this and the following chapter - iterated and paginated queries. </para>
-        <para>Iterated query is not actually a special query. Any selecting query can be executed in
-            iterated mode by the DataContext (like in the previous example, a cast to DataContext is
-            needed). DataContext returns an object called <code>ResultIterator</code> that is backed
-            by an open ResultSet. Data is read from ResultIterator one row at a time until it is
-            exhausted. Data comes as a DataRows regardless of whether the orginating query was
-            configured to fetch DataRows or not. A ResultIterator must be explicitly closed to avoid
-            JDBC resource leak.</para>
-        <para>Iterated query provides constant memory performance for arbitrarily large ResultSets.
-            This is true at least on the Cayenne end, as JDBC driver may still decide to bring the
-            entire ResultSet into the JVM memory. </para>
-        <para>Here is a full
-            example:<programlisting language="java">// you need to cast ObjectContext to DataContext to get access to 'performIteratedQuery'
-DataContext dataContext = (DataContext) context;
-
-// create a regular query
-SelectQuery q = new SelectQuery(Artist.class);
-
-// ResultIterator operations all throw checked CayenneException
-// moreover 'finally' is required to close it
-try {
-
-    ResultIterator it = dataContext.performIteratedQuery(q);
-
-    try {
-        while(it.hasNextRow()) {
-            // normally we'd read a row, process its data, and throw it away
-            // this gives us constant memory performance
-            Map row = (Map) it.nextRow();
-            
-            // do something with the row...
-            ...
-        }
-    }
-    finally {
-        it.close();
-    }
-}
-catch(CayenneException e) {
-   e.printStackTrace();
-}
-</programlisting>Also
-            common sense tells us that ResultIterators should be processed and closed as soon as
-            possible to release the DB connection. E.g. storing open iterators between HTTP requests
-            and for unpredictable length of time would quickly exhaust the connection pool.</para>
-    </section>
-    <section xml:id="paginated-queries">
-        <title>Paginated Queries</title>
-        <para>Enabling query pagination allows to load very large result sets in a Java app with
-            very little memory overhead (much smaller than even the DataRows option discussed
-            above). Moreover it is completely transparent to the application - a user gets what
-            appears to be a list of Persistent objects - there's no iterator to close or DataRows to
-            convert to objects:</para>
-        <para>
-            <programlisting language="java">SelectQuery query = new SelectQuery(Artist.class);
-query.setPageSize(50);
-
-// the fact that result is paginated is transparent
-List&lt;Artist> artists = ctxt.performQuery(query);</programlisting>
-        </para>
-        <para>Having said that, DataRows option can be combined with pagination, providing the best
-            of both
-            worlds:<programlisting language="java">SelectQuery query = new SelectQuery(Artist.class);
-query.setPageSize(50);
-query.setFetchingDataRows(true);
-
-List&lt;DataRow> rows = ctxt.performQuery(query);</programlisting></para>
-        <para>The way pagination works internally, it first fetches a list of IDs for the root
-            entity of the query. This is very fast and initially takes very little memory. Then when
-            an object is requested at an arbitrary index in the list, this object and adjacent
-            objects (a "page" of objects that is determined by the query pageSize parameter) are
-            fetched together by ID. Subsequent requests to the objects of this "page" are served
-            from memory.</para>
-        <para>An obvious limitation of pagination is that if you eventually access all objects in
-            the list, the memory use will end up being the same as with no pagination. However it is
-            still a very useful approach. With some lists (e.g. multi-page search results) only a
-            few top objects are normally accessed. At the same time pagination allows to estimate
-            the full list size without fetching all the objects. And again - it is completely
-            transparent and looks like a normal query.</para>
-    </section>
-    <section xml:id="caching-and-fresh-data">
-        <title>Caching and Fresh Data</title>
-        <section xml:id="object-caching">
-            <title>Object Caching</title>
-        </section>
-        <section xml:id="query-result-caching">
-            <title>Query Result Caching</title>
-        </section>
-    </section>
-    <section xml:id="turning-off-synchronization-of-objectcontexts">
-        <title>Turning off Synchronization of ObjectContexts</title>
-        <para>By default when a single ObjectContext commits its changes, all other contexts in the
-            same runtime receive an event that contains all the committed changes. This allows them
-            to update their cached object state to match the latest committed data. There are
-            however many problems with this ostensibly helpful feature. In short - it works well in
-            environments with few contexts and in unclustered scenarios, such as single user desktop
-            applications, or simple webapps with only a few users. More specifically:<itemizedlist>
-                <listitem>
-                    <para>The performance of synchronization is (probably worse than) O(N) where N
-                        is the number of peer ObjectContexts in the system. In a typical webapp N
-                        can be quite large. Besides for any given context, due to locking on
-                        synchronization, context own performance will depend not only on the queries
-                        that it runs, but also on external events that it does not control. This is
-                        unacceptable in most situations. </para>
-                </listitem>
-                <listitem>
-                    <para>Commit events are untargeted - even contexts that do not hold a given
-                        updated object will receive the full event that they will have to
-                        process.</para>
-                </listitem>
-                <listitem>
-                    <para>Clustering between JVMs doesn't scale - apps with large volumes of commits
-                        will quickly saturate the network with events, while most of those will be
-                        thrown away on the receiving end as mentioned above.</para>
-                </listitem>
-                <listitem>
-                    <para>Some contexts may not want to be refreshed. A refresh in the middle of an
-                        operation may lead to unpredictable results. </para>
-                </listitem>
-                <listitem>
-                    <para>Synchronization will interfere with optimistic locking. </para>
-                </listitem>
-            </itemizedlist>So we've made a good case for disabling synchronization in most webapps.
-            To do that, set to "false" the following DI property -
-                <code>Constants.SERVER_CONTEXTS_SYNC_PROPERTY</code>, using one of the standard
-            Cayenne DI approaches. E.g. from command
-            line:<programlisting language="java">java -Dcayenne.server.contexts_sync_strategy=false</programlisting>Or
-            by changing the standard properties Map in a custom extensions
-            module:<programlisting language="java">public class MyModule implements Module {
-
-    @Override
-    public void configure(Binder binder) {
-        binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.SERVER_CONTEXTS_SYNC_PROPERTY, "false");
-    }
-}</programlisting></para>
-    </section>
-</chapter>

http://git-wip-us.apache.org/repos/asf/cayenne/blob/7783cd34/docs/docbook/cayenne-guide/src/docbkx/persistent-objects-objectcontext.xml
----------------------------------------------------------------------
diff --git a/docs/docbook/cayenne-guide/src/docbkx/persistent-objects-objectcontext.xml b/docs/docbook/cayenne-guide/src/docbkx/persistent-objects-objectcontext.xml
deleted file mode 100644
index 471cca1..0000000
--- a/docs/docbook/cayenne-guide/src/docbkx/persistent-objects-objectcontext.xml
+++ /dev/null
@@ -1,300 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one or more
-    contributor license agreements. See the NOTICE file distributed with
-    this work for additional information regarding copyright ownership.
-    The ASF licenses this file to you under the Apache License, Version
-    2.0 (the "License"); you may not use this file except in compliance
-    with the License. You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0 Unless required by
-    applicable law or agreed to in writing, software distributed under the
-    License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-    CONDITIONS OF ANY KIND, either express or implied. See the License for
-    the specific language governing permissions and limitations under the
-    License.
--->
-<chapter xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink"
-    version="5.0" xml:id="persistent-objects-objectcontext">
-    <title>Persistent Objects and ObjectContext</title>
-    <section xml:id="objectcontext">
-        <title>ObjectContext</title>
-        <para>ObjectContext is an interface that users normally work with to access the database. It
-            provides the API to execute database operations and to manage persistent objects. A
-            context is obtained from the
-            ServerRuntime:<programlisting language="java">ObjectContext context = runtime.getContext();</programlisting></para>
-        <para>The call above creates a new instance of ObjectContext that can access the database via this
-            runtime. ObjectContext is a single "work area" in Cayenne, storing persistent objects.
-            ObjectContext guarantees that for each database row with a unique ID it will contain at
-            most one instance of an object, thus ensuring object graph consistency between multiple
-            selects (a feature called "uniquing"). At the same time different ObjectContexts will
-            have independent copies of objects for each unique database row. This allows users to
-            isolate object changes from one another by using separate ObjectContexts.</para>
-        <para>These properties directly affect the strategies for scoping and sharing (or not
-            sharing) ObjectContexts. Contexts that are only used to fetch objects from the database
-            and whose objects are never modified by the application can be shared between mutliple
-            users (and multiple threads). Contexts that store modified objects should be accessed
-            only by a single user (e.g. a web application user might reuse a context instance
-            between multiple web requests in the same HttpSession, thus carrying uncommitted changes
-            to objects from request to request, until he decides to commit or rollback them). Even
-            for a single user it might make sense to use mutliple ObjectContexts (e.g.
-            request-scoped contexts to allow concurrent requests from the browser that change and
-            commit objects independently).</para>
-        <para>ObjectContext is serializable and does not permanently hold to any of the application
-            resources. So it does not have to be closed. If the context is not used anymore, it
-            should simply be allowed to go out of scope and get garbage collected, just like any
-            other Java object.</para>
-    </section>
-    <section xml:id="persistent-lifecycle">
-        <title>Persistent Object and its Lifecycle</title>
-        <para>Cayenne can persist Java objects that implement <code>org.apache.cayenne.Persistent</code>
-            interface. Generally persistent classes are generated from the model as described above,
-            so users do not have to worry about superclass and property implementation details. </para>
-        <para>Persistent interface provides access to 3 persistence-related properties - objectId,
-            persistenceState and objectContext. All 3 are initialized by Cayenne runtime framework.
-            Application code should not attempt to change them them. However it is allowed to read
-            them, which provides valuable runtime information. E.g. ObjectId can be used for quick
-            equality check of 2 objects, knowing persistence state would allow highlighting changed
-            objects, etc.</para>
-        <para>Each persistent object belongs to a single ObjectContext, and can be in one of the following
-            persistence states (as defined in <code>org.apache.cayenne.PersistenceState</code>)
-                :<table frame="void">
-                <caption>Persistence States</caption>
-                <col width="16%"/>
-                <col width="84%"/>
-                <tbody>
-                    <tr>
-                        <td>TRANSIENT</td>
-                        <td>The object is not registered with an ObjectContext and will not be
-                            persisted.</td>
-                    </tr>
-                    <tr>
-                        <td>NEW</td>
-                        <td>The object is freshly registered in an ObjectContext, but has not been
-                            saved to the database yet and there is no matching database row.</td>
-                    </tr>
-                    <tr>
-                        <td>COMMITTED</td>
-                        <td>The object is registered in an ObjectContext, there is a row in the
-                            database corresponding to this object, and the object state corresponds
-                            to the last known state of the matching database row.</td>
-                    </tr>
-                    <tr>
-                        <td>MODIFIED</td>
-                        <td>The object is registered in an ObjectContext, there is a row in the
-                            database corresponding to this object, but the object in-memory state
-                            has diverged from the last known state of the matching database
-                            row.</td>
-                    </tr>
-                    <tr>
-                        <td>HOLLOW</td>
-                        <td>The object is registered in an ObjectContext, there is a row in the
-                            database corresponding to this object, but the object state is unknown.
-                            Whenever an application tries to access a property of such object,
-                            Cayenne attempts reading its values from the database and "inflate" the
-                            object, turning it to COMMITED.</td>
-                    </tr>
-                    <tr>
-                        <td>DELETED</td>
-                        <td>The object is registered in an ObjectContext and has been marked for
-                            deletion in-memory. The corresponding row in the database will get
-                            deleted upon ObjectContext commit, and the object state will be turned
-                            into TRANSIENT.</td>
-                    </tr>
-                </tbody>
-            </table></para>
-    </section>
-    <section xml:id="persistent-operations">
-        <title>ObjectContext Persistence API</title>
-        <para>One of the first things users usually want to do with an ObjectContext is to select
-            some objects from a database. This is done by calling "<emphasis role="italic"
-                >performQuery</emphasis>"
-            method:<programlisting language="java">SelectQuery query = new SelectQuery(Artist.class);
-List&lt;Artist> artists = context.performQuery(query);</programlisting>We'll
-            discuss queries in some detail in the following chapters. The example above is
-            self-explanatory - we create a SelectQuery that matches all Artist objects present in
-            the database, and then call "performQuery", getting a list of Artist objects.</para>
-        <para>Some queries can be quite complex, returning multiple result sets or even updating the
-            database. For such queries ObjectContext provides "<emphasis role="italic"
-                >performGenericQuery</emphasis>"method. While not nearly as commonly-used as
-            "performQuery", it is nevertheless important in some situations.
-            E.g.:<programlisting language="java">Collection&lt;Query> queries = ... // multiple queries that need to be run together
-QueryChain query = new QueryChain(queries);
-
-QueryResponse response = context.performGenericQuery(query);</programlisting></para>
-        <para>An application might modify selected objects. E.g.:</para>
-        <programlisting language="java">Artist selectedArtist = artists.get(0);
-selectedArtist.setName("Dali");</programlisting>
-        <para>The first time the object property is changed, the object's state is automatically set
-            to "MODIFIED" by Cayenne. Cayenne tracks all in-memory changes until a user calls
-                "<emphasis role="italic"
-            >commitChanges</emphasis>":<programlisting language="java">context.commitChanges();</programlisting>At
-            this point all in-memory changes are analyzed and a minimal set of SQL statements is
-            issued in a single transaction to synchronize the database with the in-memory state. In
-            our example "commitChanges" commits just one object, but generally it can be any number
-            of objects. </para>
-        <para>If instead of commit, we wanted to reset all changed objects to the previously
-            committed state, we'd call <emphasis>rollbackChanges</emphasis>
-            instead:<programlisting language="java">context.rollbackChanges();</programlisting></para>
-        <para>"<emphasis role="italic">newObject</emphasis>" method call creates a persistent object
-            and sets its state to
-            "NEW":<programlisting language="java">Artist newArtist = context.newObject(Artist.class);
-newArtist.setName("Picasso");</programlisting></para>
-        <para>It will only exist in memory until "commitChanges" is issued. On commit Cayenne might
-            generate a new primary key (unless a user set it explicitly, or a PK was inferred from a
-            relationship) and issue an INSERT SQL statement to permanently store the object.</para>
-        <para><emphasis>deleteObjects</emphasis> method takes one or more Persistent objects and
-            marks them as
-            "DELETED":<programlisting language="java">context.deleteObjects(artist1);
-context.deleteObjects(artist2, artist3, artist4);</programlisting>Additionally
-            "deleteObjects" processes all  delete rules modeled for the affected objects. This may
-            result in implicitly deleting or modifying extra related objects. Same as insert and
-            update, delete operations are sent to the database only when "commitChanges" is called.
-            Similarly "rollbackChanges" will undo the effect of "newObject" and
-            "deleteObjects".</para>
-        <para><emphasis>localObject</emphasis> returns a copy of a given persistent object that is
-            "local" to a given ObjectContext:</para>
-        <para>Since an application often works with more than one context, "localObject" is a rather
-            common operation. E.g. to improve performance a user might utilize a single shared
-            context to select and cache data, and then occasionally transfer some selected objects
-            to another context to modify and commit
-            them:<programlisting language="java">ObjectContext editingContext = runtime.getContext();
-Artist localArtist = editingContext.localObject(artist);</programlisting></para>
-        <para>Often an appliction needs to inspect mapping metadata. This information is stored in
-            the EntityResolver object, accessible via the
-            ObjectContext:<programlisting language="java">EntityResolver resolver = objectContext.getEntityResolver();</programlisting></para>
-        <para>Here we discussed the most commonly used subset of the ObjectContext API. There are
-            other useful methods, e.g. those allowing to inspect registered objects state en bulk,
-            etc. Check the latest JavaDocs for details.</para>
-    </section>
-    <section xml:id="cayenne-helper-class">
-        <title>Cayenne Helper Class</title>
-        <para>There is a useful helper class called "Cayenne" (fully-qualified name
-                <code>"org.apache.cayenne.Cayenne"</code>) that builds on ObjectContext API to
-            provide a number of very common operations. E.g. get a primary key (most entities do not
-            model PK as an object property)
-            :<programlisting language="java">long pk = Cayenne.longPKForObject(artist);</programlisting></para>
-        <para>It also provides the reverse operation - finding an object given a known
-            PK:<programlisting language="java">Artist artist = Cayenne.objectForPK(context, Artist.class, 34579);</programlisting></para>
-        <para>If a query is expected to return 0 or 1 object, Cayenne helper class can be used to find
-            this object. It throws an exception if more than one object matched the
-            query:<programlisting language="java">Artist artist = (Artist) Cayenne.objectForQuery(context, new SelectQuery(Artist.class));</programlisting></para>
-        <para>Feel free to explore Cayenne class API for other useful methods.</para>
-    </section>
-    <section xml:id="objectcontext-nesting">
-        <title>ObjectContext Nesting</title>
-        <para>In all the examples shown so far an ObjectContext would directly connect to a database
-            to select data or synchronize its state (either via commit or rollback). However another
-            context can be used in all these scenarios instead of a database. This concept is called
-            ObjectContext "nesting". Nesting is a parent/child relationship between two contexts,
-            where child is a nested context and selects or commits its objects via a parent. </para>
-        <para>Nesting is useful to create isolated object editing areas (child contexts) that need
-            to all be committed to an intermediate in-memory store (parent context), or rolled back
-            without affecting changes already recorded in the parent. Think cascading GUI dialogs,
-            or parallel AJAX requests coming to the same session.</para>
-        <para>In theory Cayenne supports any number of nesting levels, however applications should
-            generally stay with one or two, as deep hierarchies will most certainly degrade the
-            performance of the deeply nested child contexts. This is due to the fact that each
-            context in a nesting chain has to update its own objects during most operations. </para>
-        <para>Cayenne ROP is an extreme case of nesting when a child context is located in a
-            separate JVM and communicates with its parent via a web service. ROP is discussed in
-            details in the following chapters. Here we concentrate on the same-VM nesting.</para>
-        <para>To create a nested context, use an instance of ServerRuntime, passing it the desired
-            parent:<programlisting language="java">ObjectContext parent = runtime.getContext();
-ObjectContext nested = runtime.getContext((DataChannel) parent);</programlisting>From
-            here a nested context operates just like a regular context (you can perform queries,
-            create and delete objects, etc.). The only difference is that commit and rollback
-            operations can either be limited to synchronization with the parent, or cascade all the
-            way to the
-            database:<programlisting language="java">// merges nested context changes into the parent context
-nested.commitChangesToParent();
-
-// regular 'commitChanges' cascades commit through the chain 
-// of parent contexts all the way to the database
-nested.commitChanges();</programlisting><programlisting language="java">// unrolls all local changes, getting context in a state identical to parent
-nested.rollbackChangesLocally();
-
-// regular 'rollbackChanges' cascades rollback through the chain of contexts 
-// all the way to the topmost parent
-nested.rollbackChanges();</programlisting></para>
-    </section>
-    <section xml:id="generic-persistent-objects">
-        <title>Generic Persistent Objects</title>
-        <para>As described in the CayenneModeler chapter, Cayenne supports mapping of completely
-            generic classes to specific entities. Although for conveniece most applications should
-            stick with entity-specific class mappings, the generic feature offers some interesting
-            possibilities, such as creating mappings completely on the fly in a running application,
-            etc.</para>
-        <para>Generic objects are first class citizens in Cayenne, and all common persistent
-            operations apply to them as well. There are some pecularities however, described
-            below.</para>
-        <para>When creating a new generic object, either cast your ObjectContext to DataContext
-            (that provides "newObject(String)" API), or provide your object with an explicit
-            ObjectId:<programlisting language="java">DataObject generic = ((DataContext) context).newObject("GenericEntity");</programlisting><programlisting language="java">DataObject generic = new CayenneDataObject();
-generic.setObjectId(new ObjectId("GenericEntity"));
-context.registerNewObject(generic);</programlisting>SelectQuery
-            for generic object should be created passing entity name String in constructor, instead
-            of a Java
-            class:<programlisting language="java">SelectQuery query = new SelectQuery("GenericEntity");</programlisting>Use
-            DataObject API to access and modify properties of a generic
-            object:<programlisting language="java">String name = (String) generic.readProperty("name");
-generic.writeProperty("name", "New Name");</programlisting>This
-            is how an application can obtain entity name of a generic
-            object:<programlisting language="java">String entityName = generic.getObjectId().getEntityName();</programlisting></para>
-    </section>
-    <section xml:id="transactions">
-        <title>Transactions</title>
-        <para>Considering how much attention is given to managing transactions in most other ORMs,
-            transactions have been conspicuously absent from the ObjectContext discussion till now.
-            The reason is that transactions are seamless in Cayenne in all but a few special cases.
-            ObjectContext is an in-memory container of objects that is disconnected from the
-            database, except when it needs to run an operation. So it does not care about any
-            surrounding transaction scope. Sure enough all database operations are transactional, so
-            when an application does a commit, all SQL execution is wrapped in a database
-            transaction. But this is done behind the scenes and is rarely a concern to the
-            application code.</para>
-        <para>Two cases where transactions need to be taken into consideration are container-managed
-            and application-managed transactions. </para>
-        <para>If you are using an EJB container (or some other JTA environment), you'll likely need
-            to switch Cayenne runtime into "external transactions mode".  This is either done in the
-            Modeler (check DataDomain > 'Container-Managed Transactions' checkbox), or in the
-            code:<programlisting language="java">runtime.getDataDomain().setUsingExternalTransactions(true);</programlisting>In
-            this case Cayenne assumes that JDBC Connections obtained by runtime whenever that might
-            happen are all coming from a transactional DataSource managed by the container. In this
-            case Cayenne does not attempt to commit or rollback the connections, leaving it up to
-            the container to do that when appropriate.</para>
-        <para>In the second scenario, an application might need to define its own transaction scope
-            that spans more than one Cayenne operation. E.g. two sequential commits that need to be
-            rolled back together in case of failure. This can be done with an explicit thread-bound
-            transaction that surrounds a set of operations. Application is responsible for
-            committing or rolling it
-            back:<programlisting language="java">Transaction tx = runtime.getDataDomain().createTransaction();
-Transaction.bindThreadTransaction(tx);
-
-try {
-    // commit one or more contexts
-    context1.commitChanges();
-    context2.commitChanges();
-    ....
-    // after changing some objects in context1, commit again
-    context1.commitChnages();
-    ....
-    // if no failures, commit
-    tx.commit();
-}
-catch (Exception ex) {
-    tx.setRollbackOnly();
-}
-finally {
-    Transaction.bindThreadTransaction(null);
- 
-    if (tx.getStatus() == Transaction.STATUS_MARKED_ROLLEDBACK) {
-        try {
-           tx.rollback();
-        }
-        catch (Exception rollbackEx) {
-        }
-    }
-} </programlisting></para>
-    </section>
-</chapter>