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/30 12:51:08 UTC

cayenne git commit: Update documentation - match latest API - remove empty ROP sections - remove mentions of deprecated code - add cross-links and styling

Repository: cayenne
Updated Branches:
  refs/heads/master f9b725a56 -> 4517505ba


Update documentation
 - match latest API
 - remove empty ROP sections
 - remove mentions of deprecated code
 - add cross-links and styling


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/4517505b
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/4517505b
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/4517505b

Branch: refs/heads/master
Commit: 4517505ba5218f0d0bec58dea97648f679fc710d
Parents: f9b725a
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Jan 30 15:51:01 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Jan 30 15:51:01 2018 +0300

----------------------------------------------------------------------
 .../_cayenne-guide/part2/customize.adoc         |  50 ++++----
 .../_cayenne-guide/part2/lifecycle.adoc         |  30 +++--
 .../_cayenne-guide/part2/objectContext.adoc     | 123 ++++++++++++++-----
 .../asciidoc/_cayenne-guide/part2/tuning.adoc   |  64 ++--------
 .../src/docs/asciidoc/_cayenne-guide/part3.adoc |  13 +-
 .../_cayenne-guide/part3/ropDeployment.adoc     |  18 ++-
 .../_cayenne-guide/part5/cacheInvalidation.adoc |   2 +-
 7 files changed, 154 insertions(+), 146 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/4517505b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc
index 1ef29e7..924a160 100644
--- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/customize.adoc
@@ -250,25 +250,29 @@ public class MyDbAdapterDetector implements DbAdapterDetector {
 
 [source, Java]
 ----
-// since build-in list for this key is a singleton, repeated
-// calls to 'bindList' will return the same instance
-binder.bindList(DefaultDbAdapterFactory.DETECTORS_LIST)
-       .add(MyDbAdapterDetector.class);
+ServerModule.contributeAdapterDetectors(binder)
+    .add(MyDbAdapterDetector.class);
 ----
 
-Maps are customized using a similar `"bindMap"` method.
-
 The names of built-in collections are listed in "Appendix B".
 
 ===== Alternative Service Implementations
 
-As mentioned above, custom modules are loaded by ServerRuntime after the built-in modules. So it is easy to redefine a built-in service in Cayenne by rebinding desired implementations or providers. To do that, first we need to know what those services to redefine are. While we describe some of them in the following sections, the best way to get a full list is to check the source code of the Cayenne version you are using and namely look in `org.apache.cayenne.configuration.server.ServerModule` - the main built-in module in Cayenne.
+As mentioned above, custom modules are loaded by ServerRuntime after the built-in modules.
+So it is easy to redefine a built-in service in Cayenne by rebinding desired implementations or providers.
+To do that, first we need to know what those services to redefine are.
+While we describe some of them in the following sections, the best way to get a full list
+is to check the source code of the Cayenne version you are using and
+namely look in `org.apache.cayenne.configuration.server.ServerModule` - the main built-in module in Cayenne.
 
-Now an example of overriding `QueryCache` service. The default implementation of this service is provided by `MapQueryCacheProvider`. But if we want to use `EhCacheQueryCache` (a Cayenne wrapper for the EhCache framework), we can define it like this:
+Now an example of overriding `JdbcEventLogger` service. The default implementation of this service
+is provided by `Slf4jJdbcEventLogger`. But if we want to use `FormattedSlf4jJdbcEventLogger`
+(a logger with basic SQL formatting), we can define it like this:
 
 [source, Java]
 ----
-binder.bind(QueryCache.class).to(EhCacheQueryCache.class);
+binder.bind(JdbcEventLogger.class)
+    .to(FormattedSlf4jJdbcEventLogger.class);
 ----
 
 ==== Using custom data types
@@ -335,11 +339,14 @@ Last step is to register this new type in `ServerRuntime`:
 ----
 ServerRuntime runtime = ServerRuntime.builder()
     .addConfig("cayenne-project.xml")
-    .addModule(binder -> ServerModule.contributeValueObjectTypes(binder).add(MoneyValueObjectType.class))
+    .addModule(binder ->
+        ServerModule.contributeValueObjectTypes(binder)
+            .add(MoneyValueObjectType.class))
     .build();
 ----
 
-More examples of implementation you can find in https://github.com/apache/cayenne/tree/master/cayenne-joda[cayenne-joda module].
+More examples of implementation you can find in
+https://github.com/apache/cayenne/blob/master/cayenne-server/src/main/java/org/apache/cayenne/access/types/LocalDateValueType.java[cayenne-server].
 
 ===== Extended Types
 
@@ -419,29 +426,14 @@ public class DoubleArrayType implements ExtendedType {
 }
 ----
 
-//For Java7
-//
-//[source, Java]
-//----
-// add DoubleArrayType to list of user types
-//ServerRuntime runtime = ServerRuntime.builder()
-//                .addConfig("cayenne-project.xml")
-//                .addModule(new Module() {
-//                    @Override
-//                    public void configure(Binder binder) {
-//                        ServerModule.contributeUserTypes(binder).add(new DoubleArrayType());
-//                    }
-//                })
-//                .build();
-//----
-
-
 [source, Java]
 ----
 // add DoubleArrayType to list of user types
 ServerRuntime runtime = ServerRuntime.builder()
                 .addConfig("cayenne-project.xml")
-                .addModule(binder -> ServerModule.contributeUserTypes(binder).add(new DoubleArrayType()))
+                .addModule(binder ->
+                    ServerModule.contributeUserTypes(binder)
+                        .add(new DoubleArrayType()))
                 .build();
 ----
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4517505b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
index 9305723..4457ef3 100644
--- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/lifecycle.adoc
@@ -130,10 +130,15 @@ Ignore the annotations for a minute. The important point here is that the listen
 
 [source, Java]
 ----
-ServerRuntime runtime = ...
-
-runtime.getDataDomain().addListener(new Listener1());
-runtime.getDataDomain().addListener(new Listener2());
+ServerRuntime runtime = ServerRuntime.builder()
+       // ..
+       .addModule(binder ->
+            ServerModule.contributeDomainListeners()
+                .add(new Listener1())
+                .add(new Listener2())
+       )
+       // ..
+       .build();
 ----
 
 
@@ -253,14 +258,15 @@ Now since this is both a filter and a listener, it needs to be registered as suc
 
 [source, Java]
 ----
-CommittedObjectCounter counter = new CommittedObjectCounter();
-
-ServerRuntime runtime = ...
-DataDomain domain = runtime.getDataDomain();
-
-// register filter
-// this will also add it as a listener (since 3.2)
-domain.addFilter(counter);
+// this will also add filter as a listener
+ServerRuntime runtime = ServerRuntime.builder()
+        // ..
+        .addModule(b ->
+                ServerModule.contributeDomainFilters(b)
+                        .add(CommittedObjectCounter.class)
+        )
+        // ..
+        .build();
 ----
 
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4517505b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc
index 115cb20..5ee0fdc 100644
--- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/objectContext.adoc
@@ -66,17 +66,21 @@ Each persistent object belongs to a single ObjectContext, and can be in one of t
 
 ==== ObjectContext Persistence API
 
-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 "performQuery" method:
+One of the first things users usually want to do with an `ObjectContext` is to select some objects from a database:
 
 [source, java]
 ----
-SelectQuery query = new SelectQuery(Artist.class);
-List<Artist> artists = context.performQuery(query);
+List<Artist> artists = ObjectSelect.query(Artist.class)
+    .select(context);
 ----
 
-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.
+We'll discuss queries in some detail in the <<queries,Queries>> chapter. The example above is self-explanatory -
+we create a `ObjectSelect` that matches all `Artist` objects present in the database, and then use `select`
+to get the result.
 
-Some queries can be quite complex, returning multiple result sets or even updating the database. For such queries ObjectContext provides "performGenericQuery"method. While not nearly as commonly-used as "performQuery", it is nevertheless important in some situations. E.g.:
+Some queries can be quite complex, returning multiple result sets or even updating the database.
+For such queries ObjectContext provides `performGenericQuery()` method.
+While not commonly-used, it is nevertheless important in some situations. E.g.:
 
 [source, java]
 ----
@@ -95,23 +99,27 @@ Artist selectedArtist = artists.get(0);
 selectedArtist.setName("Dali");
 ----
 
-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 "commitChanges":
+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 `commitChanges`:
 
 [source, java]
 ----
 context.commitChanges();
 ----
 
-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.
+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.
 
-If instead of commit, we wanted to reset all changed objects to the previously committed state, we'd call `rollbackChanges` instead:
+If instead of commit, we wanted to reset all changed objects to the previously committed state,
+we'd call `rollbackChanges` instead:
 
 [source, java]
 ----
 context.rollbackChanges();
 ----
 
-"newObject" method call creates a persistent object and sets its state to "NEW":
+`newObject` method call creates a persistent object and sets its state to *NEW*:
 
 [source, java]
 ----
@@ -119,9 +127,11 @@ Artist newArtist = context.newObject(Artist.class);
 newArtist.setName("Picasso");
 ----
 
-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.
+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.
 
-`deleteObjects` method takes one or more Persistent objects and marks them as "DELETED":
+`deleteObjects` method takes one or more Persistent objects and marks them as *DELETED*:
 
 [source, java]
 ----
@@ -129,11 +139,16 @@ context.deleteObjects(artist1);
 context.deleteObjects(artist2, artist3, artist4);
 ----
 
-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".
+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`.
 
-`localObject` returns a copy of a given persistent object that is "local" to a given ObjectContext:
+`localObject` returns a copy of a given persistent object that is _local_ to a given ObjectContext:
 
-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:
+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:
 
 
 [source, java]
@@ -142,18 +157,23 @@ ObjectContext editingContext = runtime.newContext();
 Artist localArtist = editingContext.localObject(artist);
 ----
 
-Often an appliction needs to inspect mapping metadata. This information is stored in the EntityResolver object, accessible via the ObjectContext:
+Often an application needs to inspect mapping metadata. This information is stored in the `EntityResolver` object,
+accessible via the `ObjectContext`:
 
 [source, java]
 ----
 EntityResolver resolver = objectContext.getEntityResolver();
 ----
 
-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 in bulk, etc. Check the latest JavaDocs for details.
+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 in bulk, etc.
+Check the latest JavaDocs for details.
 
 ==== Cayenne Helper Class
 
-There is a useful helper class called "Cayenne" (fully-qualified name `"org.apache.cayenne.Cayenne"`) 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) :
+There is a useful helper class called `Cayenne` (fully-qualified name `org.apache.cayenne.Cayenne`)
+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) :
 
 [source, java]
 ----
@@ -177,23 +197,36 @@ Artist artist = (Artist) Cayenne.objectForQuery(context, new SelectQuery(Artist.
 Feel free to explore Cayenne class API for other useful methods.
 
 ==== ObjectContext Nesting
-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.
+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.
 
-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.
+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.
 
-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.
+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.
 
-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.
+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.
 
 To create a nested context, use an instance of ServerRuntime, passing it the desired parent:
 
 [source, java]
 ----
 ObjectContext parent = runtime.newContext();
-ObjectContext nested = runtime.newContext((DataChannel) parent);
+ObjectContext nested = runtime.newContext(parent);
 ----
 
-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:
+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:
 
 [source, java]
 ----
@@ -217,11 +250,16 @@ nested.rollbackChanges();
 
 ==== Generic Persistent Objects
 
-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.
+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.
 
-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.
+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.
 
-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:
+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:
 
 [source, java]
 ----
@@ -260,13 +298,29 @@ String entityName = generic.getObjectId().getEntityName();
 
 ==== Transactions
 
-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.
-
-Two cases where transactions need to be taken into consideration are container-managed and application-managed transactions.
-
-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 done by setting DI configuration property defined in `Constants.SERVER_EXTERNAL_TX_PROPERTY` (see Appendix A). If this property is set to "true", 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.
-
-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 via `ServerRuntime.performInTransaction` method:
+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.
+
+Two cases where transactions need to be taken into consideration are container-managed and
+application-managed transactions.
+
+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 done by setting DI configuration property defined in `Constants.SERVER_EXTERNAL_TX_PROPERTY` (see Appendix A).
+If this property is set to "true", 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.
+
+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 via `ServerRuntime.performInTransaction` method:
 
 [source, java]
 ----
@@ -284,7 +338,8 @@ Integer result = runtime.performInTransaction(() -> {
 });
 ----
 
-When inside the transaction, current thread Transaction object can be accessed via a static method. E.g. here is an example that initializes transaction JDBC connection with a custom connection object :
+When inside the transaction, current thread Transaction object can be accessed via a static method.
+E.g. here is an example that initializes transaction JDBC connection with a custom connection object :
 
 [source, java]
 ----

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4517505b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/tuning.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/tuning.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/tuning.adoc
index 5c1961e..43919d6 100644
--- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/tuning.adoc
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/tuning.adoc
@@ -291,39 +291,9 @@ Those are arbitrary names that allow to categorize queries for the purpose of se
 
 The above API is enough for the caching to work, but by default your cache is an unmanaged LRU map. You can't control its size,
 expiration policies, etc. For the managed cache, you will need to explicitly use one of the more advanced cache providers.
-One such provider available in Cayenne is a provider for http://www.ehcache.org[EhCache].
-It can be enabled on ServerRuntime startup in a custom Module:
+Use can use <<ext-cayenne-jcache,JCache integration module>> to enable any of JCache API compatible caching providers.
 
-[source, Java]
-----
-ServerRuntimeBuilder
-  .builder()
-  .addModule((binder) ->
-     binder.bind(QueryCache.class).to(EhCacheQueryCache.class)
-  )
-  .build();
-----
-
-By default EhCache reads a file called "ehcache.xml" located on classpath. You can put your cache configuration in that file. E.g.:
-
-[source, XML]
-----
-<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="false"
-	monitoring="off" dynamicConfig="false">
-
-	<defaultCache maxEntriesLocalHeap="1000" eternal="false"
-		overflowToDisk="false" timeToIdleSeconds="3600" timeToLiveSeconds="3600">
-	</defaultCache>
-
-	<cache name="artists" timeToLiveSeconds="20" maxEntriesLocalHeap="100" />
-</ehcache>
-----
-
-The example shows how to configure default cache settings ("defaultCache") as well as settings for a named cache group ("artists").
-For many other things you can put in "ehcache.xml" refer to EhCache docs.
-
-Often "passive" cache expiration policies similar to shown above are not sufficient, and the users want real-time cache invalidation when the data changes.
+Often "passive" cache expiration policies used by caching providers are not sufficient, and the users want real-time cache invalidation when the data changes.
 So in addition to those policies, the app can invalidate individual cache groups explicitly with `RefreshQuery`:
 
 [source, Java]
@@ -332,30 +302,9 @@ RefreshQuery refresh = new RefreshQuery("artist");
 context.performGenericQuery(refresh);
 ----
 
-The above can be used e.g. to build UI for manual cache invalidation. It is also possible to automate cache refresh when certain entities are committed.
-This requires including `cayenne-lifecycle.jar` deoendency. From that library you will need two things: `@CacheGroups` annotation
-to mark entities that generate cache invalidation events and  `CacheInvalidationFilter` that catches the updates to the annotated objects and generates appropriate invalidation events:
-
-[source, Java]
-----
-// configure filter on startup
-ServerRuntimeBuilder
-  .builder()
-  .addModule((binder) ->
-     binder.bindList(Constants.SERVER_DOMAIN_FILTERS_LIST).add(CacheInvalidationFilter.class)
-  )
-  .build();
-----
-
-
-Now you can associate entities with cache groups, so that commits to those entities would atomatically invalidate the groups:
-
-[source, Java]
-----
-@CacheGroups("artists")
-public class Artist extends _Artist {
-}
-----
+The above can be used e.g. to build UI for manual cache invalidation.
+It is also possible to automate cache refresh when certain entities are committed.
+This can be done with the help of <<ext-cache-invalidation,Cache invalidation extension>>.
 
 Finally you may cluster cache group events. They are very small and can be efficiently sent over the wire to other JVMs running Cayenne.
 An example of Cayenne setup with event clustering is https://github.com/andrus/wowodc13/tree/master/services/src/main/java/demo/services/cayenne[available on GitHub].
@@ -397,7 +346,8 @@ public class MyModule implements Module {
 
     @Override
     public void configure(Binder binder) {
-        binder.bindMap(Constants.PROPERTIES_MAP).put(Constants.SERVER_CONTEXTS_SYNC_PROPERTY, "false");
+        ServerModule.contributeProperties(binder)
+            .put(Constants.SERVER_CONTEXTS_SYNC_PROPERTY, "false");
     }
 }
 ----

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4517505b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3.adoc
index 5e211d1..0bf6e6e 100644
--- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3.adoc
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3.adoc
@@ -15,14 +15,11 @@
 == Cayenne Framework - Remote Object Persistence
 
 include::part3/rop.adoc[]
-
-include::part3/ropSetup.adoc[]
-
-include::part3/serverImpl.adoc[]
-
-include::part3/clientImpl.adoc[]
-
 include::part3/ropDeployment.adoc[]
 
-include::part3/limitations.adoc[]
+// TODO: add content to these files:
+//include::part3/ropSetup.adoc[]
+//include::part3/serverImpl.adoc[]
+//include::part3/clientImpl.adoc[]
+//include::part3/limitations.adoc[]
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4517505b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/ropDeployment.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/ropDeployment.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/ropDeployment.adoc
index 6aa4388..230aef8 100644
--- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/ropDeployment.adoc
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part3/ropDeployment.adoc
@@ -14,9 +14,17 @@
 
 === ROP Deployment
 
-==== Deploying ROP Server
+==== Server Security Note
 
-NOTE: Recent versions of Tomcat and Jetty containers (e.g. Tomcat 6 and 7, Jetty 8) contain code addressing a security concern related to "session fixation problem" by resetting the existing session ID of any request that requires BASIC authentcaition. If ROP service is protected with declarative security (see the ROP tutorial and the following chapters on security), this feature prevents the ROP client from attaching to its session, resulting in MissingSessionExceptions. To solve that you will need to either switch to an alternative security mechanism, or disable "session fixation problem" protections of the container. E.g. the later can be achieved in Tomcat 7 by adding the following context.xml file to the webapp's META-INF/ directory:
+Recent versions of Tomcat and Jetty containers (e.g. Tomcat 6 and 7, Jetty 8) contain code
+addressing a security concern related to "session fixation problem" by resetting the existing session ID of any request
+that requires BASIC authentication. If ROP service is protected with declarative security
+(see the ROP tutorial and the following chapters on security), this feature prevents the ROP client
+from attaching to its session, resulting in `MissingSessionExceptions`.
+
+To solve that you will need to either switch to an alternative security mechanism,
+or disable "session fixation problem" protections of the container.
+E.g. the later can be achieved in Tomcat 7 by adding the following `context.xml` file to the webapp's `META-INF/` directory:
 
 [source, XML]
 ----
@@ -26,9 +34,9 @@ NOTE: Recent versions of Tomcat and Jetty containers (e.g. Tomcat 6 and 7, Jetty
 </Context>
 ----
 
-(The <Valve> tag can also be placed within the <Context> in any other locations used by Tomcat to load context configurations)
+(The `<Valve>` tag can also be placed within the `<Context>` in any other locations used by Tomcat to load context configurations)
 
-==== Deploying ROP Client
+//==== Deploying ROP Client
 
-==== Security
+//==== Security
 

http://git-wip-us.apache.org/repos/asf/cayenne/blob/4517505b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part5/cacheInvalidation.adoc
----------------------------------------------------------------------
diff --git a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part5/cacheInvalidation.adoc b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part5/cacheInvalidation.adoc
index f79ec45..3dfd4b4 100644
--- a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part5/cacheInvalidation.adoc
+++ b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part5/cacheInvalidation.adoc
@@ -80,7 +80,7 @@ Now we'll set up it's usage by `ServerRuntime`:
 ----
 ServerRuntime.builder()
         .addModule(CacheInvalidationModule.extend()
-                // this will disable default handler based on @CacheGroups, and this is optional
+                // optionally you can disable @CacheGroups annotation processing
                 .noCacheGroupsHandler()
                 .addHandler(CustomInvalidationHandler.class)
                 .module())