Add documentation describing the IsDirtyPredicate strategy interface.
Resolves gh-17.
This commit is contained in:
@@ -1071,10 +1071,10 @@ in {data-store-name}.
|
||||
[[httpsession-gemfire-serialization-framework-data-serialization-support]]
|
||||
===== Additional Support for Data Serialization
|
||||
|
||||
NOTE: Please feel free to skip this section if configuring and bootstraping {data-store-name} servers in your cluster
|
||||
using Spring (Boot) as generally, the information that follows will not apply. Of course, it all depends on your
|
||||
declared dependencies and your Spring configuration. However, if you are using *_Gfsh_* to start the servers
|
||||
in your cluster, then definitely read on.
|
||||
NOTE: Please feel free to skip this section if you are configuring and bootstraping {data-store-name} servers
|
||||
in your cluster using Spring (Boot) since generally, the information that follows will not apply. Of course,
|
||||
it all depends on your declared dependencies and your Spring configuration. However, if you are using *_Gfsh_*
|
||||
to start the servers in your cluster, then definitely read on.
|
||||
|
||||
====== Background
|
||||
|
||||
@@ -1184,6 +1184,161 @@ Keep in mind, you may need to add your application domain object JAR files to th
|
||||
|
||||
To get a complete picture of how this works, see the {gh-samples-url}boot/gemfire-with-gfsh-servers[sample].
|
||||
|
||||
[[httpsession-gemfire-serialization-framework-session-deltas]]
|
||||
===== Customizing Change Detection
|
||||
|
||||
By default, anytime the Session is modified (e.g. the `lastAccessedTime` is updated to the current time), the Session
|
||||
is considered dirty by Spring Session for {data-store-name} (SSDG). When using {data-store-name} _Data Serialization_
|
||||
framework, it is extremely useful and valuable to take advantage of {data-store-name}'s
|
||||
{data-store-docs}/developing/delta_propagation/chapter_overview.html[Delta Propagation] capabilities as well.
|
||||
|
||||
When using _Data Serialization_, SSDG also uses _Delta Propagation_ to send only changes to the Session state between
|
||||
the client and server. This includes any Session attributes that may have been added, removed or updated.
|
||||
|
||||
By default, anytime `Session.setAttribute(name, value)` is called, the Session attribute is considered "dirty"
|
||||
and will be sent in the delta between the client and server. This is true even if your application domain object
|
||||
has not been changed.
|
||||
|
||||
Typically, there is never a reason to call `Session.setAttribute(..)` unless your object has been changed. However,
|
||||
if this can occur, and your objects are relatively large (with a complex object hierarchy), then you may want to
|
||||
consider either:
|
||||
|
||||
1. Implementing the {data-store-javadoc}/org/apache/geode/Delta.html[Delta] interface in your application domain object
|
||||
model, while useful, is very invasive, or...
|
||||
|
||||
2. Provide a custom implementation of SSDG's `org.springframework.session.data.gemfire.support.IsDirtyPredicate`
|
||||
strategy interface.
|
||||
|
||||
Out of the box, SSDG provides 5 implementations of the `IsDirtyPredicate` strategy interface:
|
||||
|
||||
[cols="2,4,1", options="header"]
|
||||
.`IsDirtyPredicate` implementations
|
||||
|===
|
||||
| Class | Description | Default
|
||||
|
||||
| `IsDirtyPredicate.ALWAYS_DIRTY` | New Session attribute values are always considered dirty. |
|
||||
|
||||
| `IsDirtyPredicate.NEVER_DIRTY` | New Session attribute values are never considered dirty. |
|
||||
|
||||
| `DeltaAwareDirtyPredicate` | New Session attribute values are considered dirty when the old value and new value
|
||||
are different, if the new value's type does not implement `Delta` or the new value's `Delta.hasDelta()`
|
||||
method returns *true*. | Yes
|
||||
|
||||
| `EqualsDirtyPredicate` | New Session attribute values are considered dirty iff the old value is not equal to
|
||||
the new value as determined by `Object.equals(:Object)` method. |
|
||||
|
||||
| `IdentityEqualsPredicate` | New Session attributes values are considered dirty iff the old value is not the same as
|
||||
the new value using the identity equals operator (i.e. `oldValue != newValue`). |
|
||||
|
||||
|===
|
||||
|
||||
As shown in the table above, the `DeltaAwareDirtyPredicate` is the *default* implementation used by SSDG.
|
||||
The `DeltaAwareDirtyPredicate` automatically takes into consideration application domain objects that implement
|
||||
the {data-store-name} `Delta` interface. However, `DeltaAwareDirtyPredicate` works even when your application
|
||||
domain objects do not implement the `Delta` interface. SSDG will consider your application domain object to be dirty
|
||||
anytime the `Session.setAttribute(name, newValue)` is called providing the new value is not the same as old value,
|
||||
or the new value does not implement the `Delta` interface.
|
||||
|
||||
You can change SSDG's dirty implementation, determination strategy simply by declaring a bean in the Spring container
|
||||
of the `IsDirtyPredicate` interface type:
|
||||
|
||||
.Overriding SSDG's default `IsDirtyPredicate` strategy
|
||||
[source,java]
|
||||
----
|
||||
@EnableGemFireHttpSession
|
||||
class ApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
IsDirtyPredicate equalsDirtyPredicate() {
|
||||
return EqualsDirtyPredicate.INSTANCE;
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
====== Composition
|
||||
|
||||
The `IsDirtyPredicate` interface also provides the `andThen(:IsDirtyPredicate)` and `orThen(:IsDirtyPredicate)` methods
|
||||
to compose 2 or more `IsDirtyPredicate` implementations in a composition in order to organize complex logic and rules
|
||||
for determining whether an application domain object is dirty or not.
|
||||
|
||||
For instance, you could compose both `EqualsDirtyPredicate` and `DeltaAwareDirtyPredicate` using the OR operator:
|
||||
|
||||
.Composing `EqualsDirtyPredicate` with `DeltaAwareDirtyPredicate` using the logical OR operator
|
||||
[source,java]
|
||||
----
|
||||
@EnableGemFireHttpSession
|
||||
class ApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
IsDirtyPredicate equalsOrThenDeltaDirtyPredicate() {
|
||||
|
||||
return EqualsDirtyPredicate.INSTANCE
|
||||
.orThen(DeltaAwareDirtyPredicate.INSTANCE);
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
You may even implement your own, custom `IsDirtyPredicates` based on specific application domain object types:
|
||||
|
||||
.Application Domain Object Type-specific `IsDirtyPredicate` implementations
|
||||
[source,java]
|
||||
----
|
||||
|
||||
class CustomerDirtyPredicate implements IsDirtyPredicate {
|
||||
|
||||
public boolean isDirty(Object oldCustomer, Object newCustomer) {
|
||||
|
||||
if (newCustomer instanceof Customer) {
|
||||
// custom logic to determine if a new Customer is dirty
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class AccountDirtyPredicate implements IsDirtyPredicate {
|
||||
|
||||
public boolean isDirty(Object oldAccount, Object newAccount) {
|
||||
|
||||
if (newAccount instanceof Account) {
|
||||
// custom logic to determine if a new Account is dirty
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
Then combine `CustomerDirtyPredicate` with the `AccountDirtyPredicate` and a default predicate for fallback, as follows:
|
||||
|
||||
.Composed and configured type-specific `IsDirtyPredicates`
|
||||
[source,java]
|
||||
----
|
||||
@EnableGemFireHttpSession
|
||||
class ApplicationConfiguration {
|
||||
|
||||
@Bean
|
||||
IsDirtyPredicate typeSpecificDirtyPredicate() {
|
||||
|
||||
return new CustomerDirtyPredicate()
|
||||
.andThen(new AccountDirtyPredicate())
|
||||
.andThen(IsDirtyPredicate.ALWAYS_DIRTY);
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
----
|
||||
|
||||
The combinations and possibilities are endless.
|
||||
|
||||
WARNING: Use caution when implementing custom `IsDirtyPredicate` strategies. If you incorrectly determine that your
|
||||
application domain object is not dirty when it actually is, then it will not be sent in the Session delta
|
||||
from the client to the server.
|
||||
|
||||
[[httpsession-gemfire-serialization-framework-session-representation]]
|
||||
===== Changing the Session Representation
|
||||
|
||||
|
||||
Reference in New Issue
Block a user