This is an automated email from the ASF dual-hosted git repository.

aadamchik pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit a40a9a41d538654fc79bb7d57bfa6d175ed07b20
Author: Eduard <5306834+kaga...@users.noreply.github.com>
AuthorDate: Tue Jul 11 03:02:55 2023 +0300

    PR#21 on `cayenne-website` mirror in actual source
---
 .../asciidoc/_cayenne-guide/part2/expressions.adoc |  82 +++++-----------
 .../_cayenne-guide/part2/objectContext.adoc        | 109 +++++++--------------
 .../asciidoc/_cayenne-guide/part2/starting.adoc    |  16 ++-
 3 files changed, 64 insertions(+), 143 deletions(-)

diff --git 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
index 3901497ae..6ab8bce59 100644
--- 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
+++ 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/expressions.adoc
@@ -14,18 +14,11 @@
 
 === Expressions
 
-Cayenne provides a simple yet powerful object-based expression language. The 
most common use of expressions are to build
-qualifiers and orderings of queries that are later converted to SQL by Cayenne 
and to evaluate in-memory against specific
-objects (to access certain values in the object graph or to perform in-memory 
object filtering and sorting).
-Cayenne provides API to build expressions in the code and a parser to create 
expressions from strings.
+Cayenne provides a simple, yet powerful, object-based expression language. The 
most common uses of expressions are to build qualifiers and orderings of 
queries that are later converted to SQL by Cayenne and to evaluate in-memory 
against specific objects (to access certain values in the object graph or to 
perform in-memory object filtering and sorting). Cayenne provides an API to 
build expressions in the code and a parser to create expressions from strings.
 
 ==== Path Expressions
 
-Before discussing how to build expressions, it is important to understand one 
group of expressions widely used
-in Cayenne - path expressions. There are two types of path expressions - 
object and database, used for navigating graphs
-of connected objects or joined DB tables respectively. Object paths are much 
more commonly used, as after all
-Cayenne is supposed to provide a degree of isolation of the object model from 
the database. However database paths
-are helpful in certain situations. General structure of path expressions is 
the following:
+Before discussing how to build expressions, it is important to understand one 
group of expressions widely used in Cayenne - path expressions. There are two 
types of path expressions - object and database, used for navigating graphs of 
connected objects or joined DB tables, respectively. Object paths are much more 
commonly used, as, after all, Cayenne is supposed to provide a degree of 
isolation of the object model from the database. However, database paths are 
helpful in certain situatio [...]
 
 [source, java]
 ----
@@ -34,7 +27,7 @@ are helpful in certain situations. General structure of path 
expressions is the
 
 - `db:` is an optional prefix indicating that the following path is a DB path. 
Otherwise it is an object path.
 
-- `segment` is a name of a property (relationship or attribute in Cayenne 
terms) in the path. Path must have at least one segment; segments are separated 
by dot (".").
+- `segment` is a name of a property (relationship or attribute in Cayenne 
terms) in the path. The path must have at least one segment; segments are 
separated by dot (".").
 
 - `+` An "OUTER JOIN" path component. Currently "+" only has effect when 
translated to SQL as OUTER JOIN. When evaluating expressions in memory, it is 
ignored.
 
@@ -53,26 +46,22 @@ is a named foreign key constraint. But DbRelationship names 
are usually chosen a
 without regard to constraints naming or even constraints presence).
 A database path therefore might look like this - 
`db:dbrelationshipX.dbrelationshipY.COLUMN_Z"`. More specific examples:
 
-- `db:NAME` - can be used to navigate to the value of "NAME" column of some 
unspecified table.
+- `db:NAME` - can be used to navigate to a value in the "NAME" column of some 
unspecified table.
 
 - `db:artist.artistExhibits.exhibit.CLOSING_DATE` - can be used to match a 
closing date of any of the exhibits of a related artist record.
 
-Cayenne supports "aliases" in path Expressions. E.g. the same expression can 
be written using explicit path or an alias:
+Cayenne supports "aliases" in path expressions. E.g. the same expression can 
be written using the explicit path or an alias:
 
 - `artist.exhibits.closingDate` - full path
 
 - `e.closingDate` - alias "e" is used for `artist.exhibits`.
 
-SelectQuery using the second form of the path expression must be made aware of 
the alias via `SelectQuery.aliasPathSplits(..)`,
-otherwise an Exception will be thrown.
-The main use of aliases is to allow users to control how SQL joins are 
generated if the same path is encountered more than once in any given 
Expression.
-Each alias for any given path would result in a separate join. Without 
aliases, a single join will be used for a group of matching paths.
+SelectQuery using the second form of the path expression must be made aware of 
the alias via `SelectQuery.aliasPathSplits(..)`;
+otherwise, an `Exception` will be thrown. The main use of aliases is to allow 
users to control how SQL joins are generated if the same path is encountered 
more than once in any given `Expression`. Each alias for any given path would 
result in a separate join. Without aliases, a single join will be used for a 
group of matching paths.
 
 ==== Creating Expressions from Strings
 
-While in most cases users are likely to rely on API from the following section 
for expression creation, we'll start by showing String expressions,
-as this will help to understand the semantics. A Cayenne expression can be 
represented as a String,
-which can be converted to an expression object using `ExpressionFactory.exp` 
static method. Here is an example:
+While in most cases users are likely to rely on the API from the following 
section for expression creation, we'll start by showing String expressions, as 
this will help you understand the semantics. A Cayenne expression can be 
represented as a String, which can be converted to an expression object using 
the `ExpressionFactory.exp` static method. Here is an example:
 
 
 [source, java]
@@ -81,11 +70,7 @@ String expString = "name like 'A%' and price < 1000";
 Expression exp = ExpressionFactory.exp(expString);
 ----
 
-This particular expression may be used to match Paintings whose names that 
start with "A" and whose price is less than $1000.
-While this example is pretty self-explanatory, there are a few points worth 
mentioning. "name" and "price" here are object paths discussed earlier.
-As always, paths themselves are not attached to a specific root entity and can 
be applied to any entity that has similarly named attributes or relationships.
-So when we are saying that this expression "may be used to match Paintings", 
we are implying that there may be other entities, for which this expression is 
valid.
-Now the expression details...
+This particular expression may be used to match Paintings whose names start 
with "A" and whose price is less than $1000. While this example is pretty 
self-explanatory, there are a few points worth mentioning. "name" and "price" 
here are object paths discussed earlier. As always, paths themselves are not 
attached to a specific root entity and can be applied to any entity that has 
similarly named attributes or relationships. So, when we say that this 
expression "may be used to match Painti [...]
 
 Character constants that are not paths or numeric values should be enclosed in 
single or double quotes. Two of the expressions below are equivalent:
 
@@ -116,8 +101,8 @@ Grouping with parenthesis:
 value = (price + 250.00) * 3
 ----
 
-Path prefixes. Object expressions are unquoted strings, optionally prefixed by 
`obj:` (usually they are not prefixed at all actually).
-Database expressions are always prefixed with `db:`. A special kind of prefix, 
not discussed yet is `enum:` that prefixes an enumeration constant:
+Path prefixes. Object expressions are unquoted strings, optionally prefixed by 
`obj:` (usually they are not prefixed at all).
+Database expressions are always prefixed with `db:`. A special kind of prefix, 
not discussed yet, is `enum:` that prefixes an enumeration constant:
 
 [source, java]
 ----
@@ -137,8 +122,7 @@ db:NAME = 'Salvador Dali'
 name = enum:org.foo.EnumClass.VALUE1
 ----
 
-Binary conditions are expressions that contain a path on the left, a value on 
the right, and some operation between them, such as equals, like, etc.
-They can be used as qualifiers in SelectQueries:
+Binary conditions are expressions that contain a path on the left, a value on 
the right, and some operation between them, such as equals like, etc. They can 
be used as qualifiers in SelectQueries:
 
 [source, java]
 ----
@@ -146,10 +130,7 @@ name like 'A%'
 ----
 
 
-Parameters. Expressions can contain named parameters (names that start with 
"$") that can be substituted with values either by name or by position.
-Parameterized expressions allow to create reusable expression templates. Also 
if an Expression contains a complex object that doesn't have a simple
-String representation (e.g. a Date, a DataObject, an ObjectId), parameterizing 
such expression is the only way to represent it as String.
-Here are the examples of both positional and named parameter bindings:
+Parameters. Expressions can contain named parameters (names that start with 
"$") that can be substituted with values either by name or by position. 
Parameterized expressions let you create reusable expression templates. Also, 
if an expression contains a complex object that doesn’t have a simple String 
representation (e.g. a Date, a DataObject, an ObjectId), parameterizing the 
expression is the only way to represent it as String. Here are examples of both 
positional and named parameter bindings:
 
 [source, java]
 ----
@@ -170,7 +151,7 @@ Positional binding is usually shorter. You can pass 
positional bindings to the `
 Expression qualifier = ExpressionFactory.exp("name = $name", "Monet");
 ----
 
-In parameterized expressions with LIKE clause, SQL wildcards must be part of 
the values in the Map and not the expression string itself:
+In parameterized expressions with a LIKE clause, SQL wildcards must be part of 
the values in the Map and not the expression string itself:
 
 [source, java]
 ----
@@ -181,13 +162,11 @@ When matching on a relationship, the value parameter must 
be either a Persistent
 
 [source, java]
 ----
-Artist dali = ... // asume we fetched this one already
+Artist dali = ... // assume we fetched this one already
 Expression qualifier = ExpressionFactory.exp("artist = $artist", dali);
 ----
 
-When using positional binding, Cayenne would expect values for all parameters 
to be present. Binding by name offers extra flexibility:
-subexpressions with uninitialized parameters are automatically pruned from the 
expression.
-So e.g. if certain parts of the expression criteria are not provided to the 
application, you can still build a valid expression:
+When you use positional binding, Cayenne expects values for all parameters to 
be present. Binding by name offers extra flexibility: sub-expressions with 
uninitialized parameters are automatically pruned from the expression. So, 
e.g., if certain parts of the expression criteria are not provided to the 
application, you can still build a valid expression
 
 
 [source, java]
@@ -202,16 +181,13 @@ Expression qualifier1 = template.params(p1);
 // the $date parameter
 ----
 
-Null handling. Handling of Java nulls as operands is no different from normal 
values. Instead of using special conditional operators,
-like SQL does (`IS NULL`, `IS NOT NULL`), "=" and "!=" expressions are used 
directly with null values. It is up to Cayenne to translate expressions with 
nulls to the valid SQL.
+Null handling. Handling of Java nulls as operands is no different handling 
from normal values. Instead of using special conditional operators, like SQL 
does (`IS NULL`, `IS NOT NULL`), "=" and "!=" expressions are used directly 
with null values. It is up to Cayenne to translate expressions with nulls to 
the valid SQL.
 
 //NOTE: A formal definition of the expression grammar is provided in 
xref:appendixC[Appendix C]
 
 ==== Creating Expressions via API
 
-Creating expressions from Strings is a powerful and dynamic approach, however 
a safer alternative is to use Java API.
-It provides compile-time checking of expressions validity. The API in question 
is provided by `ExpressionFactory` class (that we've seen already),
-Property class and Expression class itself. `ExpressionFactory` contains a 
number of self-explanatory static methods that can be used to build 
expressions. E.g.:
+Creating expressions from Strings is a powerful and dynamic approach, however 
a safer alternative is to use the Java API. It provides compile-time checking 
of the expression's validity. The API in question is provided by the 
`ExpressionFactory` class (that we've seen already), the Property class and the 
Expression class itself. `ExpressionFactory` contains a number of 
self-explanatory static methods that can be used to build expressions. E.g.:
 
 [source, java]
 ----
@@ -221,12 +197,9 @@ Expression e2 = ExpressionFactory.lessExp("price", 1000);
 Expression finalExp = e1.andExp(e2);
 ----
 
-NOTE: The last line in the example above shows how to create a new expression 
by "chaining" two other expressions.
-A common error when chaining expressions is to assume that "andExp" and 
"orExp" append another expression to the current expression.
-In fact a new expression is created. I.e. Expression API treats existing 
expressions as immutable.
+NOTE: The last line in the example above shows how to create a new expression 
by "chaining" two other expressions. A common error when chaining expressions 
is to assume that "andExp" and "orExp" append another expression to the current 
expression. In fact, a new expression is created. Expression API treats 
existing expressions as immutable.
 
-As discussed earlier, Cayenne supports aliases in path Expressions, allowing 
to control how SQL joins are generated
-if the same path is encountered more than once in the same Expression. Two 
ExpressionFactory methods allow to implicitly generate aliases to "split" match 
paths into individual joins if needed:
+As discussed earlier, Cayenne supports aliases in path Expressions, so you can 
control how SQL joins are generated if the same path is encountered more than 
once in the same Expression. Two ExpressionFactory methods let you implicitly 
generate aliases to "split" match paths into individual joins if needed:
 
 [source, java]
 ----
@@ -234,12 +207,9 @@ Expression matchAllExp(String path, Collection values)
 Expression matchAllExp(String path, Object... values)
 ----
 
-"Path" argument to both of these methods can use a split character (a pipe 
symbol '|') instead of dot to indicate that relationship
-following a path should be split into a separate set of joins, one per 
collection value. There can only be one split at most in any given path.
-Split must always precede a relationship. E.g. `"|exhibits.paintings"`, 
`"exhibits|paintings"`, etc.
-Internally Cayenne would generate distinct aliases for each of the split 
expressions, forcing separate joins.
+The "Path" argument to both of these methods can use a split character (a pipe 
symbol '|') instead of a dot to indicate that the relationship following a path 
should be split into a separate set of joins, one per collection value. There 
can only be one split at most in any given path. The split must always precede 
a relationship. E.g. `"|exhibits.paintings"`, `"exhibits|paintings"`, etc. 
Internally, Cayenne generates distinct aliases for each of the split 
expressions, forcing separate joins.
 
-While ExpressionFactory is pretty powerful, there's an even easier way to 
create expression using static Property objects generated by Cayenne for each 
persistent class.
+While ExpressionFactory is pretty powerful, there's an even easier way to 
create an expression using static Property objects generated by Cayenne for 
each persistent class.
 Some examples:
 
 [source, java]
@@ -247,20 +217,18 @@ Some examples:
 // Artist.NAME is generated by Cayenne and has a type of Property<String>
 Expression e1 = Artist.NAME.eq("Pablo");
 
-// Chaining multiple properties into a path..
+// Chaining multiple properties into a path.
 // Painting.ARTIST is generated by Cayenne and has a type of Property<Artist>
 Expression e2 = Painting.ARTIST.dot(Artist.NAME).eq("Pablo");
 ----
 
-Property objects provide the API mostly analogius to ExpressionFactory, though 
it is significantly shorter and is aware of the value types.
+Property objects provide the API mostly analogous to ExpressionFactory, though 
it is significantly shorter and is aware of the value types.
 It provides compile-time checks of both property names and types of arguments 
in conditions. We will use Property-based API in further examples.
 
 [[evaluate]]
 ==== Evaluating Expressions in Memory
 
-When used in a query, an expression is converted to SQL WHERE clause (or ORDER 
BY clause) by Cayenne during query execution.
-Thus the actual evaluation against the data is done by the database engine. 
However the same expressions can also be used
-for accessing object properties, calculating values, in-memory filtering.
+When used in a query, an expression is converted to a SQL WHERE or ORDER BY 
clause by Cayenne during query execution. Thus the actual evaluation against 
the data is done by the database engine. However, the same expressions can also 
be used for accessing object properties, calculating values, and in-memory 
filtering.
 
 
 Checking whether an object satisfies an expression:
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 1e19d6758..cf39d5b3c 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
@@ -24,18 +24,18 @@ ObjectContext is an interface that users normally work with 
to access the databa
 ObjectContext context = runtime.newContext();
 ----
 
-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 [...]
+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 uni [...]
 
-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  [...]
+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 multiple 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  [...]
 
-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.
+ObjectContext is serializable and does not permanently hold 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.
 
 
 ==== Persistent Object and its Lifecycle
 
-Cayenne can persist Java objects that implement 
`org.apache.cayenne.Persistent` 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.
+Cayenne can persist Java objects that implement the 
`org.apache.cayenne.Persistent` 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.
 
-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. 
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.
+The `Persistent` interface provides access to three persistence-related 
properties - _objectId_, _persistenceState_ and _objectContext_. All three are 
initialized by the Cayenne runtime framework. Your application code should not 
attempt to change them. However, it is allowed to read them, which provides 
valuable runtime information. E.g. ObjectId can be used for a quick equality 
check of two objects, knowing persistence state would allow highlighting 
changed objects, etc.
 
 Each persistent object belongs to a single ObjectContext, and can be in one of 
the following persistence states (as defined in 
`org.apache.cayenne.PersistenceState`) :
 
@@ -51,14 +51,14 @@ Each persistent object belongs to a single ObjectContext, 
and can be in one of t
 |*NEW*
 |The object is freshly registered in an ObjectContext, but has not been saved 
to the database yet and there is no matching database row.
 
-|*COMMITED*
+|*COMMITTED*
 |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.
 
 |*MODIFIED*
 |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.
 
 |*HOLLOW*
-|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.
+|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 COMMITTED.
 
 |*DELETED*
 |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.
@@ -79,8 +79,8 @@ we create a `ObjectSelect` that matches all `Artist` objects 
present in the data
 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 commonly-used, it is nevertheless important in some situations. E.g.:
+For such queries, ObjectContext provides the `performGenericQuery()` method.
+While not commonly used, it is nevertheless important in some situations. E.g.:
 
 [source, java]
 ----
@@ -99,20 +99,16 @@ 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]
 ----
@@ -127,11 +123,9 @@ 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 only exists 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*:
+The `deleteObjects` method takes one or more `Persistent` objects and marks 
them as *DELETED*:
 
 [source, java]
 ----
@@ -139,16 +133,14 @@ context.deleteObjects(artist1);
 context.deleteObjects(artist2, artist3, artist4);
 ----
 
-Additionally `deleteObjects` processes all delete rules modeled for the 
affected objects.
+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:
 
-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]
@@ -165,15 +157,11 @@ accessible via the `ObjectContext`:
 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 you 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 the 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]
 ----
@@ -187,25 +175,16 @@ It also provides the reverse operation - finding an 
object given a known PK:
 Artist artist = Cayenne.objectForPK(context, Artist.class, 34579);
 ----
 
-For more flexibility, you could use <<SelectById>> query instead.
+For more flexibility, you could use the <<SelectById>> query instead.
 
-Feel free to explore `Cayenne` class API for other useful methods.
+Feel free to explore the `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 a 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 all need to 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 levels, as deep hierarchies 
will almost 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.
 
 To create a nested context, use an instance of ServerRuntime, passing it the 
desired parent:
 
@@ -215,9 +194,7 @@ ObjectContext parent = runtime.newContext();
 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]
 ----
@@ -241,16 +218,11 @@ 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 convenience 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.
 
-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 peculiarities, 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 generic object, either cast your ObjectContext to DataContext 
(that provides `newObject(String)` API), or provide your object with an 
explicit ObjectId:
 
 [source, java]
 ----
@@ -264,7 +236,7 @@ generic.setObjectId(ObjectId.of("GenericEntity"));
 context.registerNewObject(generic);
 ----
 
-ObjectSelect for a generic object should be created passing entity name 
String, instead of just a Java class:
+ObjectSelect for a generic object should be created by passing the entity name 
String, instead of just a Java class:
 
 [source, java]
 ----
@@ -279,7 +251,7 @@ String name = (String) generic.readProperty("name");
 generic.writeProperty("name", "New Name");
 ----
 
-This is how an application can obtain entity name of a generic object:
+This is how an application can obtain the entity name of a generic object:
 
 [source, java]
 ----
@@ -289,29 +261,14 @@ 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.
+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  [...]
 
 Two cases where transactions need to be taken into consideration are 
container- and
 application-managed transactions.
 
-If you are using Spring, EJB or another environment that manages transactions,
-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:
+If you are using Spring, EJB or another environment that manages transactions, 
you’ll likely need to switch the Cayenne runtime into "external transactions 
mode". This is done by setting the 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 cas [...]
+
+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 the `ServerRuntime.performInTransaction` method:
 
 [source, java]
 ----
diff --git 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/starting.adoc
 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/starting.adoc
index c03b9bb8a..3683c33ea 100644
--- 
a/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/starting.adoc
+++ 
b/docs/asciidoc/cayenne-guide/src/docs/asciidoc/_cayenne-guide/part2/starting.adoc
@@ -47,7 +47,6 @@ It is a good idea to shut down the runtime when it is no 
longer needed, usually
 runtime.shutdown();
 ----
 
-
 When a runtime object has the same scope as the application, this may not be 
always necessary, however in some cases it is essential, and is generally 
considered a good practice. E.g. in a web container hot redeploy of a webapp 
will cause resource leaks and eventual OutOfMemoryError if the application 
fails to shutdown CayenneRuntime.
 
 ==== Merging Multiple Projects
@@ -65,7 +64,6 @@ ServerRuntime runtime = ServerRuntime.builder()
 
 When the projects are merged, the following rules are applied:
 
-
 - The order of projects matters during merge. If there are two conflicting 
metadata objects belonging to two projects, an object from the last project 
takes precedence over the object from the first one. This makes possible to 
override pieces of metadata. This is also similar to how DI modules are merged 
in Cayenne.
 
 - Runtime DataDomain name is set to the name of the last project in the list.
@@ -80,7 +78,7 @@ When the projects are merged, the following rules are applied:
 
 ==== Web Applications
 
-Web applications can use a variety of mechanisms to configure and start the 
"services" they need, Cayenne being one of such services. Configuration can be 
done within standard Servlet specification objects like Servlets, Filters, or 
ServletContextListeners, or can use Spring, JEE CDI, etc. This is a user's 
architectural choice and Cayenne is agnostic to it and will happily work in any 
environment. As described above, all that is needed is to create an instance of 
ServerRuntime somewhere  [...]
+Web applications can use a variety of mechanisms to configure and start the 
"services" they need, Cayenne being one of such services. Configuration can be 
done within standard servlet specification objects like Servlets, Filters, or 
ServletContextListeners, or can use Spring, JEE CDI, etc. This is a user’s 
architectural choice and Cayenne is agnostic to it and will happily work in any 
environment. As described above, all that is needed is to create an instance of 
ServerRuntime somewhere  [...]
 
 Still Cayenne includes a piece of web app configuration code that can assist 
in quickly setting up simple Cayenne-enabled web applications. We are talking 
about CayenneFilter. It is declared in web.xml:
 
@@ -100,19 +98,17 @@ Still Cayenne includes a piece of web app configuration 
code that can assist in
  </web-app>
 ----
 
+When started by the web container, it creates a instance of ServerRuntime and 
stores it in the ServletContext. Note that the name of a Cayenne XML project 
file is derived from the "filter-name". In the example above, CayenneFilter 
will look for an XML file "cayenne-project.xml". This can be overridden with 
the "configuration-location" init parameter.
 
-When started by the web container, it creates a instance of ServerRuntime and 
stores it in the ServletContext. Note that the name of Cayenne XML project file 
is derived from the "filter-name". In the example above CayenneFilter will look 
for an XML file "cayenne-project.xml". This can be overridden with 
"configuration-location" init parameter.
-
-When the application runs, all HTTP requests matching the filter url-pattern 
will have access to a session-scoped ObjectContext like this:
+When the application runs, all HTTP requests matching the filter url-pattern 
have access to a session-scoped ObjectContext like this:
 
 [source, java]
 ----
  ObjectContext context = BaseContext.getThreadObjectContext();
 ----
 
-Of course the ObjectContext scope, and other behavior of the Cayenne runtime 
can be customized via dependency injection. For this another filter init 
parameter called "extra-modules" is used. "extra-modules" is a comma or 
space-separated list of class names, with each class implementing Module 
interface. These optional custom modules are loaded after the the standard 
ones, which allows users to override all standard definitions.
-
-For those interested in the DI container contents of the runtime created by 
CayenneFilter, it is the same ServerRuntime as would've been created by other 
means, but with an extra `org.apache.cayenne.configuration.web.WebModule` 
module that provides `org.apache.cayenne.configuration.web.RequestHandler` 
service. This is the service to override in the custom modules if you need to 
provide a different ObjectContext scope, etc.
+Of course, the ObjectContext scope and other behavior of the Cayenne runtime 
can be customized via dependency injection. For this, another filter init 
parameter called "extra-modules" is used. "extra-modules" is a comma- or 
space-separated list of class names, with each class implementing Module 
interface. These optional custom modules are loaded after the the standard 
ones, which allows users to override all standard definitions.
 
-NOTE: You should not think of CayenneFilter as the only way to start and use 
Cayenne in a web application. In fact CayenneFilter is entirely optional. Use 
it if you don't have any special design for application service management. If 
you do, simply integrate Cayenne into that design.
+For those interested in the DI container contents of the runtime created by 
CayenneFilter, it is the same ServerRuntime as would have been created by other 
means, but with an extra 
<code>org.apache.cayenne.configuration.web.WebModule</code> module that 
provides the <code>org.apache.cayenne.configuration.web.RequestHandler</code> 
service. This is the service to override in the custom modules if you need to 
provide a different ObjectContext scope, etc.
 
+NOTE: You should not think of CayenneFilter as the only way to start and use 
Cayenne in a web application. In fact, CayenneFilter is entirely optional. Use 
it if you don’t have any special design for application service management. If 
you do, simply integrate Cayenne into that design.


Reply via email to