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>

Reply via email to