Merge documentation edits with documentation polish.

Resolves gh-109.
This commit is contained in:
John Blum
2021-07-19 16:26:39 -07:00
24 changed files with 2149 additions and 2059 deletions

View File

@@ -1,59 +1,61 @@
[[actuator]] [[actuator]]
== Spring Boot Actuator == Spring Boot Actuator
Spring Boot for {apache-geode-name} and {pivotal-gemfire-name} (SBDG) adds {spring-boot-docs-html}/production-ready.html[Spring Boot Actuator]
support and dedicated `HealthIndicators` for {apache-geode-name} and {pivotal-gemfire-name}. Equally, the provided Spring Boot for {apache-geode-name} (SBDG) adds {spring-boot-docs-html}/production-ready.html[Spring Boot Actuator]
`HealthIndicators` even work with Pivotal Cloud Cache (which is backed by {pivotal-gemfire-name}) when you push your support and dedicated `HealthIndicators` for {apache-geode-name}. Equally, the provided `HealthIndicators` even work
Spring Boot applications to Pivotal CloudFoundry (PCC). with Tanzu Cache (which is backed by {pivotal-gemfire-name}) when you push your Spring Boot applications
using {apache-geode-name} to {VMware Tanzu Application Service (TAS)} platform.
Spring Boot `HealthIndicators` provide details about the runtime operation and behavior of your {apache-geode-name}-based Spring Boot `HealthIndicators` provide details about the runtime operation and behavior of your {apache-geode-name}-based
Spring Boot applications. For instance, by querying the right `HealthIndicator` endpoint, you can Spring Boot applications. For instance, by querying the right `HealthIndicator` endpoint, you can get the current
get the current hit/miss count for your `Region.get(key)` data access operations. hit/miss count for your `Region.get(key)` data access operations.
In addition to vital health information, SBDG provides basic, pre-runtime configuration metadata about the In addition to vital health information, SBDG provides basic, pre-runtime configuration metadata about the
{apache-geode-name} components that are monitored by Spring Boot Actuator. This makes it easier to see how {apache-geode-name} components that are monitored by Spring Boot Actuator. This makes it easier to see how
the application was configured all in one place, rather than in properties files, Spring configuration, XML, and so on. the application was configured all in one place, rather than in properties files, Spring configuration, XML,
and so on.
The provided Spring Boot `HealthIndicators` fall into three categories: The provided Spring Boot `HealthIndicators` fall into three categories:
* Base `HealthIndicators` that apply to all {apache-geode-name}, Spring Boot applications, regardless of cache type * Base `HealthIndicators` that apply to all {apache-geode-name}, Spring Boot applications, regardless of cache type,
(such as regions, indexes, and disk stores). such as `Regions`, `Indexes`, and `DiskStores`.
* Peer `Cache`-based `HealthIndicators` that apply only to peer `Cache` applications, such as * Peer `Cache`-based `HealthIndicators` that apply only to peer `Cache` applications, such as `AsyncEventQueues`,
`AsyncEventQueue`, `CacheServer`, `GatewayReceiver`, and `GatewaySender`. `CacheServers`, `GatewayReceivers`, and `GatewaySenders`.
* `ClientCache`-based `HealthIndicators` that apply only to `ClientCache` applications, such as * `ClientCache`-based `HealthIndicators` that apply only to `ClientCache` applications, such as `ContinuousQuery`
`ContinuousQuery` and connection `Pool`. and connection `Pools`.
The following sections give a brief overview of all the available Spring Boot `HealthIndicators` provided for The following sections give a brief overview of all the available Spring Boot `HealthIndicators` provided for
{apache-geode-name}. {apache-geode-name}.
TIP: See the corresponding sample link:guides/boot-actuator.html[guide] and {github-samples-url}/boot/actuator[code] TIP: See the corresponding sample link:guides/boot-actuator.html[guide] and {github-samples-url}/boot/actuator[code]
to see the Spring Boot Actuator for {apache-geode-name} in action. to see Spring Boot Actuator for {apache-geode-name} in action.
[[actuator-base-healthindicators]] [[actuator-base-healthindicators]]
=== Base HealthIndicators === Base HealthIndicators
This section covers Spring Boot `HealthIndicators` that apply to both peer `Cache` and `ClientCache`, This section covers Spring Boot `HealthIndicators` that apply to both {apache-geode-name} peer `Cache` and `ClientCache`,
Spring Boot applications. That is, these `HealthIndicators` are not specific to the cache type. Spring Boot applications. That is, these `HealthIndicators` are not specific to the cache type.
In {apache-geode-name}, the cache instance is either a peer `Cache` instance (which makes your Spring Boot application In {apache-geode-name}, the cache instance is either a peer `Cache` instance (which makes your Spring Boot application
part of a {apache-geode-name} cluster) or, more commonly, a `ClientCache` instance (which talks to an existing cluster). part of a {apache-geode-name} cluster) or, more commonly, a `ClientCache` instance (which talks to an existing cluster).
Your Spring Boot application can be only one cache type or the other and can have only a single instance of Your Spring Boot application can only be one cache type or the other and can only have a single instance of
that cache type. that cache type.
[[actuator-base-healthindicators-cache]] [[actuator-base-healthindicators-cache]]
==== GeodeCacheHealthIndicator ==== GeodeCacheHealthIndicator
`GeodeCacheHealthIndicator` provides essential details about the (single) cache instance (client or peer) and `GeodeCacheHealthIndicator` provides essential details about the (single) cache instance (client or peer)
the underlying `DistributedSystem`, the `DistributedMember`, and configuration details of the `ResourceManager`. and the underlying `DistributedSystem`, the `DistributedMember` and configuration details of the `ResourceManager`.
When your Spring Boot application creates an instance of a peer {apache-geode-javadoc}/org/apache/geode/cache/Cache.html[`Cache`], When your Spring Boot application creates an instance of a peer {apache-geode-javadoc}/org/apache/geode/cache/Cache.html[`Cache`],
the {apache-geode-javadoc}/org/apache/geode/distributed/DistributedMember.html[`DistributedMember`] object represents the {apache-geode-javadoc}/org/apache/geode/distributed/DistributedMember.html[`DistributedMember`] object represents
your application as a peer member or node of the {apache-geode-javadoc}/org/apache/geode/distributed/DistributedSystem.html[`DistributedSystem`]. The distributed system is your application as a peer member or node of the {apache-geode-javadoc}/org/apache/geode/distributed/DistributedSystem.html[`DistributedSystem`].
formed from a collection of connected peers (that is, the cluster), to which your application also has The distributed system (that is, the cluster) is formed from a collection of connected peers, to which your application
{apache-geode-javadoc}/org/apache/geode/cache/GemFireCache.html#getDistributedSystem--[access] -- also has {apache-geode-javadoc}/org/apache/geode/cache/GemFireCache.html#getDistributedSystem--[access] -- indirectly,
indirectly, through the cache instance. through the cache instance.
This is no different for a `ClientCache`, even though the client is technically not part of the peer/server cluster. This is no different for a `ClientCache` even though the client is technically not part of the peer/server cluster.
However, it still creates instances of the `DistributedSystem` and `DistributedMember` objects, respectively. However, it still creates instances of the `DistributedSystem` and `DistributedMember` objects, respectively.
Each object has the following configuration metadata and health details: Each object has the following configuration metadata and health details:
@@ -87,9 +89,9 @@ Each object has the following configuration metadata and health details:
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Name | Description
| geode.distributed-system.member-count | Total number of members in the cluster (1 for clients).
| geode.distributed-system.connected | Indicates whether the member is currently connected to | geode.distributed-system.connected | Indicates whether the member is currently connected to
the cluster. the cluster.
| geode.distributed-system.member-count | Total number of members in the cluster (1 for clients).
| geode.distributed-system.reconnecting | Indicates whether the member is in a reconnecting state, | geode.distributed-system.reconnecting | Indicates whether the member is in a reconnecting state,
which happens when a network partition occurs and the member gets disconnected from the cluster. which happens when a network partition occurs and the member gets disconnected from the cluster.
| geode.distributed-system.properties-location | Location of the | geode.distributed-system.properties-location | Location of the
@@ -108,20 +110,19 @@ which happens when a network partition occurs and the member gets disconnected f
becoming inoperable. becoming inoperable.
| geode.resource-manager.critical-off-heap-percentage | Percentage of off-heap at which the cache is in danger of | geode.resource-manager.critical-off-heap-percentage | Percentage of off-heap at which the cache is in danger of
becoming inoperable. becoming inoperable.
| geode.resource-manager.eviction-heap-percentage | Percentage of heap at which eviction begins on regions | geode.resource-manager.eviction-heap-percentage | Percentage of heap at which eviction begins on Regions
configured with a heap LRU eviction policy. configured with a heap LRU eviction policy.
| geode.resource-manager.eviction-off-heap-percentage | Percentage of off-heap at which eviction begins on regions | geode.resource-manager.eviction-off-heap-percentage | Percentage of off-heap at which eviction begins on Regions
configured with a heap LRU eviction policy. configured with a heap LRU eviction policy.
|===================================================================================================================== |=====================================================================================================================
[[actuator-base-healthindicators-regions]] [[actuator-base-healthindicators-regions]]
==== GeodeRegionsHealthIndicator ==== GeodeRegionsHealthIndicator
`GeodeRegionsHealthIndicator` provides details about all the configured and known `Region` instances in the cache. `GeodeRegionsHealthIndicator` provides details about all the configured and known `Regions` in the cache.
If the cache is a client, details include all `LOCAL`, `PROXY`, and `CACHING_PROXY` `Region` instances. If the cache If the cache is a client, details include all `LOCAL`, `PROXY`, and `CACHING_PROXY` `Regions`. If the cache is a peer
is a peer, the details include all `LOCAL`, `PARTITION`, and `REPLICATE` `Region` instances. then details include all `LOCAL`, `PARTITION`, and `REPLICATE` `Region` instances.
The following table describes the essential details and basic performance metrics: The following table describes the essential details and basic performance metrics:
@@ -130,48 +131,49 @@ The following table describes the essential details and basic performance metric
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Name | Description
| geode.cache.regions.<name>.cloning-enabled | Whether region values are cloned on read (for example, `cloning-enabled` | geode.cache.regions.<name>.cloning-enabled | Whether Region values are cloned on read (for example, `cloning-enabled`
is `true` when cache transactions are used to prevent in-place modifications). is `true` when cache transactions are used to prevent in-place modifications).
| geode.cache.regions.<name>.data-policy | Policy used to manage the data in the region | geode.cache.regions.<name>.data-policy | Policy used to manage data in the Region (`PARTITION`, `REPLICATE`,
(`PARTITION`, `REPLICATE`, and others). and others).
| geode.cache.regions.<name>.initial-capacity | Initial number of entries that can be held by a region before | geode.cache.regions.<name>.initial-capacity | Initial number of entries that can be held by a Region before it needs
it needs to be resized. to be resized.
| geode.cache.regions.<name>.load-factor | Load factor used to determine when to resize the region | geode.cache.regions.<name>.load-factor | Load factor used to determine when to resize the Region when it nears
when it nears capacity. capacity.
| geode.cache.regions.<name>.key-constraint | Type constraint for region keys. | geode.cache.regions.<name>.key-constraint | Type constraint for Region keys.
| geode.cache.regions.<name>.off-heap | Determines whether this region stores values in off-heap memory | geode.cache.regions.<name>.off-heap | Determines whether this Region stores values in off-heap memory
(NOTE: Keys are always kept on heap). (NOTE: Keys are always kept on the JVM heap).
| geode.cache.regions.<name>.pool-name | If this region is a client region, this property determines | geode.cache.regions.<name>.pool-name | If this Region is a client Region, this property determines
the configured connection `Pool`. (NOTE: Regions can have and use dedicated `Pools` for their data access operations.) the configured connection `Pool`. (NOTE: Regions can have and use dedicated `Pools` for their data access operations.)
| geode.cache.regions.<name>.pool-name | Determines the `Scope` of the region, which plays a factor in | geode.cache.regions.<name>.pool-name | Determines the `Scope` of the Region, which plays a factor in
the region's consistency-level, as it pertains to acknowledgements for writes. the Region's consistency-level, as it pertains to acknowledgements for writes.
| geode.cache.regions.<name>.value-constraint | Type constraint for region values. | geode.cache.regions.<name>.value-constraint | Type constraint for Region values.
|===================================================================================================================== |=====================================================================================================================
The following details also apply when the Region is a peer `Cache` `PARTITION` region: The following details also apply when the Region is a peer `Cache` `PARTITION` Region:
.Partition Region Details .Partition Region Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Name | Description
| geode.cache.regions.<name>.partition.collocated-with | Indicates whether this region is collocated with another | geode.cache.regions.<name>.partition.collocated-with | Indicates whether this Region is collocated with
`PARTITION` egion, which is necessary when performing equi-joins queries (NOTE: distributed joins are not supported). another `PARTITION` Region, which is necessary when performing equi-joins queries (NOTE: distributed joins
are not supported).
| geode.cache.regions.<name>.partition.local-max-memory | Total amount of heap memory allowed to be used by | geode.cache.regions.<name>.partition.local-max-memory | Total amount of heap memory allowed to be used by
this region on this node. this Region on this node.
| geode.cache.regions.<name>.partition.redundant-copies | Number of replicas for this `PARTITION` region, | geode.cache.regions.<name>.partition.redundant-copies | Number of replicas for this `PARTITION` Region,
which is useful in high availability (HA) use cases. which is useful in high availability (HA) use cases.
| geode.cache.regions.<name>.partition.total-max-memory | Total amount of heap memory allowed to be used by | geode.cache.regions.<name>.partition.total-max-memory | Total amount of heap memory allowed to be used by
this region across all nodes in the cluster hosting this region. this Region across all nodes in the cluster hosting this Region.
| geode.cache.regions.<name>.partition.total-number-of-buckets | Total number of buckets (shards) into which this region | geode.cache.regions.<name>.partition.total-number-of-buckets | Total number of buckets (shards) into which this Region
is divided (defaults to 113). is divided (defaults to 113).
|===================================================================================================================== |=====================================================================================================================
Finally, when statistics are enabled (for example, when you use `@EnableStatistics` -- Finally, when statistics are enabled (for example, when you use `@EnableStatistics` --
(see {spring-data-geode-docs-html}/#bootstrap-annotation-config-statistics[here] (see {spring-data-geode-docs-html}/#bootstrap-annotation-config-statistics[doc] for more details),
for more details), the following details are available: the following metadata is available:
.Region Statistic Details .Region Statistic Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
@@ -182,19 +184,18 @@ for more details), the following details are available:
| geode.cache.regions.<name>.statistics.hit-ratio | Ratio of hits to the number of `Region.get(key)` calls. | geode.cache.regions.<name>.statistics.hit-ratio | Ratio of hits to the number of `Region.get(key)` calls.
| geode.cache.regions.<name>.statistics.last-accessed-time | For an entry, indicates the last time it was accessed | geode.cache.regions.<name>.statistics.last-accessed-time | For an entry, indicates the last time it was accessed
with `Region.get(key)`. with `Region.get(key)`.
| geode.cache.regions.<name>.statistics.last-modified-time | For an entry, indicates the time when a region's entry value | geode.cache.regions.<name>.statistics.last-modified-time | For an entry, indicates the time when a Region's entry
was last modified. value was last modified.
| geode.cache.regions.<name>.statistics.miss-count | Returns the number of times that a `Region.get` | geode.cache.regions.<name>.statistics.miss-count | Returns the number of times that a `Region.get`
was performed and no value was found locally. was performed and no value was found locally.
|===================================================================================================================== |=====================================================================================================================
[[actuator-base-healthindicators-indexes]] [[actuator-base-healthindicators-indexes]]
==== GeodeIndexesHealthIndicator ==== GeodeIndexesHealthIndicator
`GeodeIndexesHealthIndicator` provides details about the configured region `Index` instances used in OQL query `GeodeIndexesHealthIndicator` provides details about the configured Region `Indexes` used by OQL query data access
data access operations. operations.
The following details are covered: The following details are covered:
@@ -204,31 +205,30 @@ The following details are covered:
| Name | Description | Name | Description
| geode.index.<name>.from-clause | Region from which data is selected. | geode.index.<name>.from-clause | Region from which data is selected.
| geode.index.<name>.indexed-expression | The region value fields and properties used in the index expression. | geode.index.<name>.indexed-expression | Region value fields and properties used in the Index expression.
| geode.index.<name>.projection-attributes | For map indexes, returns either `*` | geode.index.<name>.projection-attributes | For `Map` `Indexes`, returns either `*` or the specific Map keys
or the specific map keys that were indexed. For all other indexes, returns `*`. that were indexed. For all other `Indexes`, returns `*`.
| geode.index.<name>.region | Region to which the index is applied. | geode.index.<name>.region | Region to which the Index is applied.
|===================================================================================================================== |=====================================================================================================================
Additionally, when statistics are enabled (for example, when you use `@EnableStatistics` -- Additionally, when statistics are enabled (for example, when you use `@EnableStatistics` --
see {spring-data-geode-docs-html}/#bootstrap-annotation-config-statistics["`Configuring Statistics`"] see {spring-data-geode-docs-html}/#bootstrap-annotation-config-statistics["`Configuring Statistics`"] for more details),
for more details), the following details are available: the following metadata is available:
.Index Statistic Details .Index Statistic Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Name | Description
| geode.index.<name>.statistics.number-of-bucket-indexes | Number of bucket indexes created in a partitioned region. | geode.index.<name>.statistics.number-of-bucket-indexes | Number of bucket Indexes created in a PARTITION Region.
| geode.index.<name>.statistics.number-of-keys | Number of keys in this index. | geode.index.<name>.statistics.number-of-keys | Number of keys in this Index.
| geode.index.<name>.statistics.number-of-map-indexed-keys | Number of keys in this index at the highest level. | geode.index.<name>.statistics.number-of-map-indexed-keys | Number of keys in this Index at the highest level.
| geode.index.<name>.statistics.number-of-values | Number of values in this index. | geode.index.<name>.statistics.number-of-values | Number of values in this Index.
| geode.index.<name>.statistics.number-of-updates | Number of times this index has been updated. | geode.index.<name>.statistics.number-of-updates | Number of times this Index has been updated.
| geode.index.<name>.statistics.read-lock-count | Number of read locks taken on this index. | geode.index.<name>.statistics.read-lock-count | Number of read locks taken on this Index.
| geode.index.<name>.statistics.total-update-time | Total amount of time (ns) spent updating | geode.index.<name>.statistics.total-update-time | Total amount of time (ns) spent updating this Index.
this index. | geode.index.<name>.statistics.total-uses | Total number of times this Index has been accessed by
| geode.index.<name>.statistics.total-uses | Total number of times this index has been accessed by
an OQL query. an OQL query.
|===================================================================================================================== |=====================================================================================================================
@@ -237,8 +237,8 @@ an OQL query.
==== GeodeDiskStoresHealthIndicator ==== GeodeDiskStoresHealthIndicator
The `GeodeDiskStoresHealthIndicator` provides details about the configured `DiskStores` in the system or application. The `GeodeDiskStoresHealthIndicator` provides details about the configured `DiskStores` in the system or application.
Remember, `DiskStore` instances are used to overflow and persist data to disk, including type metadata tracked by PDX Remember, `DiskStores` are used to overflow and persist data to disk, including type metadata tracked by PDX when the
when the values in the regions have been serialized with PDX and the regions are persistent. values in the Regions have been serialized with PDX and the Regions are persistent.
Most of the tracked health information pertains to configuration: Most of the tracked health information pertains to configuration:
@@ -259,11 +259,12 @@ the total disk volume.
| geode.disk-store.<name>.disk-usage-warning-percentage | Warning threshold of disk usage proportional to | geode.disk-store.<name>.disk-usage-warning-percentage | Warning threshold of disk usage proportional to
the total disk volume. the total disk volume.
| geode.disk-store.<name>.max-oplog-size | Maximum size (MB) allowed for a single oplog file. | geode.disk-store.<name>.max-oplog-size | Maximum size (MB) allowed for a single oplog file.
| geode.disk-store.<name>.queue-size | Size of the queue used to batch writes that are flushed to disk. | geode.disk-store.<name>.queue-size | Size of the queue used to batch writes that are flushed
to disk.
| geode.disk-store.<name>.time-interval | Time to wait (ms) before writes are flushed to disk | geode.disk-store.<name>.time-interval | Time to wait (ms) before writes are flushed to disk
from the queue if the size limit has not be reached. from the queue if the size limit has not be reached.
| geode.disk-store.<name>.uuid | Universally unique identifier for the DiskStore across | geode.disk-store.<name>.uuid | Universally unique identifier for the DiskStore across a
a distributed system. distributed system.
| geode.disk-store.<name>.write-buffer-size | Size the of write buffer the DiskStore uses to write data | geode.disk-store.<name>.write-buffer-size | Size the of write buffer the DiskStore uses to write data
to disk. to disk.
@@ -279,23 +280,23 @@ instance (that is, the application is a cache client), which is the default.
[[actuator-clientcache-healthindicators-cq]] [[actuator-clientcache-healthindicators-cq]]
==== GeodeContinuousQueriesHealthIndicator ==== GeodeContinuousQueriesHealthIndicator
`GeodeContinuousQueriesHealthIndicator` provides details about registered client continuous queries (CQs). `GeodeContinuousQueriesHealthIndicator` provides details about registered client Continuous Queries (CQs). CQs let
CQs let client applications receive automatic notification about events that satisfy some criteria. That criteria client applications receive automatic notification about events that satisfy some criteria. That criteria can be easily
can be easily expressed by using the predicate of an OQL query (for example, `SELECT * FROM /Customers c WHERE c.age > 21`). expressed by using the predicate of an OQL query (for example, `SELECT * FROM /Customers c WHERE c.age > 21`).
When data is inserted or updated and the data matches the criteria specified in the OQL query predicate, When data is inserted or updated and the data matches the criteria specified in the OQL query predicate
an event is sent to the registered client. ("data of interests"), an event is sent to the registered client.
The following details are covered for CQs by name: The following details are covered for CQs by name:
.Continuous Query(CQ) Details .Continuous Query (CQ) Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Name | Description
| geode.continuous-query.<name>.oql-query-string | OQL query constituting the CQ. | geode.continuous-query.<name>.oql-query-string | OQL query constituting the CQ.
| geode.continuous-query.<name>.closed | Indicates whether the CQ has been closed. | geode.continuous-query.<name>.closed | Indicates whether the CQ has been closed.
| geode.continuous-query.<name>.closing | Indicates whether the CQ is the process of closing. | geode.continuous-query.<name>.closing | Indicates whether the CQ is in the process of closing.
| geode.continuous-query.<name>.durable | Indicates whether the CQ events is remembered | geode.continuous-query.<name>.durable | Indicates whether the CQ events are remembered
between client sessions. between client sessions.
| geode.continuous-query.<name>.running | Indicates whether the CQ is currently running. | geode.continuous-query.<name>.running | Indicates whether the CQ is currently running.
| geode.continuous-query.<name>.stopped | Indicates whether the CQ has been stopped. | geode.continuous-query.<name>.stopped | Indicates whether the CQ has been stopped.
@@ -304,18 +305,16 @@ between client sessions.
In addition, the following CQ query and statistical data is covered: In addition, the following CQ query and statistical data is covered:
.Continuous Query(CQ), Query Details .Continuous Query (CQ), Query Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Name | Description
| geode.continuous-query.<name>.query.number-of-executions | Total number of times the query has been executed. | geode.continuous-query.<name>.query.number-of-executions | Total number of times the query has been executed.
| geode.continuous-query.<name>.query.total-execution-time | Total amount of time (ns) spent executing the query. | geode.continuous-query.<name>.query.total-execution-time | Total amount of time (ns) spent executing the query.
| geode.continuous-query.<name>.statistics.number-of-deletes |
|===================================================================================================================== |=====================================================================================================================
.Continuous Query(CQ), Statistic Details .Continuous Query(CQ), Statistic Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -328,10 +327,9 @@ In addition, the following CQ query and statistical data is covered:
|===================================================================================================================== |=====================================================================================================================
The {apache-geode-name} continuous query system is also tracked with the following The {apache-geode-name} Continuous Query system is also tracked with the following additional details on the client:
additional details on the client:
.Continuous Query(CQ), Statistic Details .Continuous Query (CQ), Additional Statistic Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Name | Description
@@ -349,8 +347,8 @@ additional details on the client:
[[actuator-clientcache-healthindicators-pools]] [[actuator-clientcache-healthindicators-pools]]
==== GeodePoolsHealthIndicator ==== GeodePoolsHealthIndicator
`GeodePoolsHealthIndicator` provides details about all the configured client connection `Pools`. `GeodePoolsHealthIndicator` provides details about all the configured client connection `Pools`. This `HealthIndicator`
This `HealthIndicator` primarily provides configuration metadata for all the configured `Pools`. primarily provides configuration metadata for all the configured `Pools`.
The following details are covered: The following details are covered:
@@ -362,42 +360,42 @@ The following details are covered:
| geode.pool.count | Total number of client connection pools. | geode.pool.count | Total number of client connection pools.
| geode.pool.<name>.destroyed | Indicates whether the pool has been destroyed. | geode.pool.<name>.destroyed | Indicates whether the pool has been destroyed.
| geode.pool.<name>.free-connection-timeout | Configured amount of time to wait for a free connection | geode.pool.<name>.free-connection-timeout | Configured amount of time to wait for a free connection
from the pool. from the Pool.
| geode.pool.<name>.idle-timeout | The amount of time to wait before closing unused | geode.pool.<name>.idle-timeout | The amount of time to wait before closing unused, idle
idle connections, not exceeding the configured number of minimum required connections. connections, not exceeding the configured number of minimum required connections.
| geode.pool.<name>.load-conditioning-interval | How frequently the pool checks to see | geode.pool.<name>.load-conditioning-interval | How frequently the Pool checks to see whether a connection
if a connection to a given server should be moved to a different server to improve the load balance. to a given server should be moved to a different server to improve the load balance.
| geode.pool.<name>.locators | List of configured locators. | geode.pool.<name>.locators | List of configured Locators.
| geode.pool.<name>.max-connections | Maximum number of connections obtainable from the pool. | geode.pool.<name>.max-connections | Maximum number of connections obtainable from the Pool.
| geode.pool.<name>.min-connections | Minimum number of connections contained by the pool. | geode.pool.<name>.min-connections | Minimum number of connections contained by the Pool.
| geode.pool.<name>.multi-user-authentication | Determines whether the pool can be used by | geode.pool.<name>.multi-user-authentication | Determines whether the Pool can be used by multiple
multiple authenticated users. authenticated users.
| geode.pool.<name>.online-locators | Returns a list of living locators. | geode.pool.<name>.online-locators | Returns a list of living Locators.
| geode.pool.<name>.pending-event-count | Approximate number of pending subscription events | geode.pool.<name>.pending-event-count | Approximate number of pending subscription events maintained
maintained at server for this durable client pool at the time it (re)connected to the server. at the server for this durable client Pool at the time it (re)connected to the server.
| geode.pool.<name>.ping-interval | How often to ping the servers to verify they are still alive. | geode.pool.<name>.ping-interval | How often to ping the servers to verify they are still alive.
| geode.pool.<name>.pr-single-hop-enabled | Whether the client acquires a direct connection to | geode.pool.<name>.pr-single-hop-enabled | Whether the client acquires a direct connection to
the server. the server.
| geode.pool.<name>.read-timeout | Number of milliseconds to wait for a response from a server | geode.pool.<name>.read-timeout | Number of milliseconds to wait for a response from a server
before timing out the operation and trying another server (if any are available). before timing out the operation and trying another server (if any are available).
| geode.pool.<name>.retry-attempts | Number of times to retry a request after a timeout or an exception. | geode.pool.<name>.retry-attempts | Number of times to retry a request after a timeout
| geode.pool.<name>.server-group | All the servers must belong to the same group, and this or an exception.
value sets the name of that group. | geode.pool.<name>.server-group | All servers must belong to the same group, and this value
sets the name of that group.
| geode.pool.<name>.servers | List of configured servers. | geode.pool.<name>.servers | List of configured servers.
| geode.pool.<name>.socket-buffer-size | Socket buffer size for each connection made in this pool. | geode.pool.<name>.socket-buffer-size | Socket buffer size for each connection made in this pool.
| geode.pool.<name>.statistic-interval | How often to send client statistics to the server. | geode.pool.<name>.statistic-interval | How often to send client statistics to the server.
| geode.pool.<name>.subscription-ack-interval | Interval in milliseconds to wait before sending | geode.pool.<name>.subscription-ack-interval | Interval in milliseconds to wait before sending
acknowledgements to the cache server for events received from the server subscriptions. acknowledgements to the cache server for events received from the server subscriptions.
| geode.pool.<name>.subscription-enabled | Enabled server-to-client subscriptions. | geode.pool.<name>.subscription-enabled | Enabled server-to-client subscriptions.
| geode.pool.<name>.subscription-message-tracking-timeout | Time-to-live period (ms) for subscription events | geode.pool.<name>.subscription-message-tracking-timeout | Time-to-Live (TTL) period (ms) for subscription events
the client has received from the server. the client has received from the server.
| geode.pool.<name>.subscription-redundancy | Redundancy level for this pool's server-to-client | geode.pool.<name>.subscription-redundancy | Redundancy level for this Pool's server-to-client
subscriptions, which is used to ensure clients do not miss potentially important events. subscriptions, which is used to ensure clients do not miss potentially important events.
| geode.pool.<name>.thread-local-connections | Thread local connection policy for this pool. | geode.pool.<name>.thread-local-connections | Thread local connection policy for this Pool.
|===================================================================================================================== |=====================================================================================================================
[[actuator-peercache-healthindicators]] [[actuator-peercache-healthindicators]]
=== Peer Cache HealthIndicators === Peer Cache HealthIndicators
@@ -408,8 +406,8 @@ instance.
NOTE: The default cache instance created by Spring Boot for {apache-geode-name} is a `ClientCache` instance. NOTE: The default cache instance created by Spring Boot for {apache-geode-name} is a `ClientCache` instance.
TIP: To control what type of cache instance is created, such as a "`peer`", you can explicitly declare either the TIP: To control what type of cache instance is created, such as a "`peer`", you can explicitly declare either the
`@PeerCacheApplication` or, alternatively, the `@CacheServerApplication` annotation on your `@SpringBootApplication`-annotated `@PeerCacheApplication` or, alternatively, the `@CacheServerApplication` annotation on your
class. `@SpringBootApplication`-annotated class.
[[actuator-peercache-healthindicators-cacheservers]] [[actuator-peercache-healthindicators-cacheservers]]
==== GeodeCacheServersHealthIndicator ==== GeodeCacheServersHealthIndicator
@@ -433,8 +431,7 @@ is bound (useful when the system contains multiple NICs).
(useful with DNS). (useful with DNS).
| geode.cache.server.<index>.load-poll-interval | How often (ms) to query the load probe on the `CacheServer`. | geode.cache.server.<index>.load-poll-interval | How often (ms) to query the load probe on the `CacheServer`.
| geode.cache.server.<index>.max-connections | Maximum number of connections allowed to this `CacheServer`. | geode.cache.server.<index>.max-connections | Maximum number of connections allowed to this `CacheServer`.
| geode.cache.server.<index>.max-message-count | Maximum number of messages that can be queued in | geode.cache.server.<index>.max-message-count | Maximum number of messages that can be put in a client queue.
a client queue.
| geode.cache.server.<index>.max-threads | Maximum number of threads allowed in this `CacheServer` | geode.cache.server.<index>.max-threads | Maximum number of threads allowed in this `CacheServer`
to service client requests. to service client requests.
| geode.cache.server.<index>.max-time-between-pings | Maximum time between client pings. | geode.cache.server.<index>.max-time-between-pings | Maximum time between client pings.
@@ -443,14 +440,14 @@ to service client requests.
and on which it listens for client connections. and on which it listens for client connections.
| geode.cache.server.<index>.running | Determines whether this `CacheServer` is currently running | geode.cache.server.<index>.running | Determines whether this `CacheServer` is currently running
and accepting client connections. and accepting client connections.
| geode.cache.server.<index>.socket-buffer-size | Configured buffer size of the socket connection | geode.cache.server.<index>.socket-buffer-size | Configured buffer size of the socket connection used by
used by this CacheServer. this CacheServer.
| geode.cache.server.<index>.tcp-no-delay | Configures the TCP/IP `TCP_NO_DELAY` setting on outgoing sockets. | geode.cache.server.<index>.tcp-no-delay | Configures the TCP/IP `TCP_NO_DELAY` setting on outgoing sockets.
|===================================================================================================================== |=====================================================================================================================
In addition to the configuration settings shown in the preceding tab le, the `ServerLoadProbe` of the `CacheServer` tracks additional details In addition to the configuration settings shown in the preceding table, the `ServerLoadProbe` of the `CacheServer`
about the runtime characteristics of the `CacheServer`: tracks additional details about the runtime characteristics of the `CacheServer`:
.CacheServer Metrics and Load Details .CacheServer Metrics and Load Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
@@ -462,8 +459,8 @@ connections.
| geode.cache.server.<index>.load.load-per-connection | Estimate of how much load each new connection | geode.cache.server.<index>.load.load-per-connection | Estimate of how much load each new connection
adds to this server. adds to this server.
| geode.cache.server.<index>.load.subscription-connection-load | Load on the server due to subscription connections. | geode.cache.server.<index>.load.subscription-connection-load | Load on the server due to subscription connections.
| geode.cache.server.<index>.load.load-per-subscription-connection | Estimate of the how much load each new subscriber | geode.cache.server.<index>.load.load-per-subscription-connection | Estimate of how much load each new subscriber adds
adds to this server. to this server.
| geode.cache.server.<index>.metrics.client-count | Number of connected clients. | geode.cache.server.<index>.metrics.client-count | Number of connected clients.
| geode.cache.server.<index>.metrics.max-connection-count | Maximum number of connections made to this | geode.cache.server.<index>.metrics.max-connection-count | Maximum number of connections made to this
`CacheServer`. `CacheServer`.
@@ -476,10 +473,10 @@ adds to this server.
[[actuator-peercache-healthindicators-aeq]] [[actuator-peercache-healthindicators-aeq]]
==== GeodeAsyncEventQueuesHealthIndicator ==== GeodeAsyncEventQueuesHealthIndicator
`GeodeAsyncEventQueuesHealthIndicator` provides details about the configured `AsyncEventQueue` instances. AEQs can be `GeodeAsyncEventQueuesHealthIndicator` provides details about the configured `AsyncEventQueues`. AEQs can be attached to
attached to regions to configure asynchronous write-behind behavior. Regions to configure asynchronous write-behind behavior.
This `HealthIndicator` captures configuration metadata and runtime characteristics for all AEQs, as follows: This `HealthIndicator` captures configuration metadata and runtime characteristics for all AEQs:
.AsyncEventQueue Details .AsyncEventQueue Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
@@ -498,7 +495,7 @@ are forwarded to `AsyncEventListener`.
| geode.async-event-queue.<id>.max-queue-memory | Maximum memory used before data needs to be overflowed | geode.async-event-queue.<id>.max-queue-memory | Maximum memory used before data needs to be overflowed
to disk. to disk.
| geode.async-event-queue.<id>.order-policy | Order policy followed while dispatching the events to | geode.async-event-queue.<id>.order-policy | Order policy followed while dispatching the events to
`AsyncEventListener` instances. `AsyncEventListeners`.
| geode.async-event-queue.<id>.parallel | Indicates whether this queue is parallel (higher throughput) | geode.async-event-queue.<id>.parallel | Indicates whether this queue is parallel (higher throughput)
or serial. or serial.
| geode.async-event-queue.<id>.persistent | Indicates whether this queue stores events to disk. | geode.async-event-queue.<id>.persistent | Indicates whether this queue stores events to disk.
@@ -507,15 +504,14 @@ or serial.
|===================================================================================================================== |=====================================================================================================================
[[actuator-peercache-healthindicators-gateway-receivers]] [[actuator-peercache-healthindicators-gateway-receivers]]
==== GeodeGatewayReceiversHealthIndicator ==== GeodeGatewayReceiversHealthIndicator
`GeodeGatewayReceiversHealthIndicator` provide details about the configured (WAN) `GatewayReceivers`, which are `GeodeGatewayReceiversHealthIndicator` provides details about the configured (WAN) `GatewayReceivers`,
capable of receiving events from remote clusters when using {apache-geode-name}'s which are capable of receiving events from remote clusters when using {apache-geode-name}'s
{apache-geode-docs}/topologies_and_comm/multi_site_configuration/chapter_overview.html[multi-site, WAN topology]. {apache-geode-docs}/topologies_and_comm/multi_site_configuration/chapter_overview.html[multi-site, WAN topology].
This `HealthIndicator` captures configuration meta-data along with the running state for each `GatewayReceiver`: This `HealthIndicator` captures configuration metadata along with the running state for each `GatewayReceiver`:
.GatewayReceiver Details .GatewayReceiver Details
[width="90%",cols="^3,<10",options="header"] [width="90%",cols="^3,<10",options="header"]
@@ -525,10 +521,10 @@ This `HealthIndicator` captures configuration meta-data along with the running s
| geode.gateway-receiver.count | Total number of configured `GatewayReceiver` instances. | geode.gateway-receiver.count | Total number of configured `GatewayReceiver` instances.
| geode.gateway-receiver.<index>.bind-address | IP address of the NIC to which the `GatewayReceiver` | geode.gateway-receiver.<index>.bind-address | IP address of the NIC to which the `GatewayReceiver`
`ServerSocket` is bound (useful when the system contains multiple NICs). `ServerSocket` is bound (useful when the system contains multiple NICs).
| geode.gateway-receiver.<index>.end-port | End value of the port range from which the port of the `GatewayReceiver` | geode.gateway-receiver.<index>.end-port | End value of the port range from which the port of
is chosen. the `GatewayReceiver` is chosen.
| geode.gateway-receiver.<index>.host | IP address or hostname that locators tell clients | geode.gateway-receiver.<index>.host | IP address or hostname that Locators tell clients (that is,
(that is, `GatewaySender` instances) on which this `GatewayReceiver` listens. `GatewaySender` instances) on which this `GatewayReceiver` listens.
| geode.gateway-receiver.<index>.max-time-between-pings | Maximum amount of time between client pings. | geode.gateway-receiver.<index>.max-time-between-pings | Maximum amount of time between client pings.
| geode.gateway-receiver.<index>.port | Port on which this `GatewayReceiver` listens for clients | geode.gateway-receiver.<index>.port | Port on which this `GatewayReceiver` listens for clients
(that is, `GatewaySender` instances). (that is, `GatewaySender` instances).
@@ -536,17 +532,17 @@ is chosen.
and accepting client connections (from `GatewaySender` instances). and accepting client connections (from `GatewaySender` instances).
| geode.gateway-receiver.<index>.socket-buffer-size | Configured buffer size for the socket connections used by | geode.gateway-receiver.<index>.socket-buffer-size | Configured buffer size for the socket connections used by
this `GatewayReceiver`. this `GatewayReceiver`.
| geode.gateway-receiver.<index>.start-port | Start value of the port range from which the | geode.gateway-receiver.<index>.start-port | Start value of the port range from which the port of
port of the `GatewayReceiver` port is chosen. the `GatewayReceiver` is chosen.
|===================================================================================================================== |=====================================================================================================================
[[actuator-peercache-healthindicators-gateway-senders]] [[actuator-peercache-healthindicators-gateway-senders]]
==== GeodeGatewaySendersHealthIndicator ==== GeodeGatewaySendersHealthIndicator
The `GeodeGatewaySendersHealthIndicator` provides details about the configured `GatewaySender` instances. `GatewaySender` instances are The `GeodeGatewaySendersHealthIndicator` provides details about the configured `GatewaySenders`. `GatewaySender`
attached to regions in order to send region events to remote clusters in {apache-geode-name}'s instances are attached to Regions in order to send Region events to remote clusters in {apache-geode-name}'s
{apache-geode-docs}/topologies_and_comm/multi_site_configuration/chapter_overview.html[multi-site WAN topology]. {apache-geode-docs}/topologies_and_comm/multi_site_configuration/chapter_overview.html[multi-site, WAN topology].
This `HealthIndicator` captures essential configuration metadata and runtime characteristics for each `GatewaySender`: This `HealthIndicator` captures essential configuration metadata and runtime characteristics for each `GatewaySender`:
@@ -564,25 +560,26 @@ when sent.
| geode.gateway-sender.<id>.batch-time-interval | Maximum time interval that can elapse before a batch | geode.gateway-sender.<id>.batch-time-interval | Maximum time interval that can elapse before a batch
is sent. is sent.
| geode.gateway-sender.<id>.disk-store-name | Name of the `DiskStore` used to overflow and persist | geode.gateway-sender.<id>.disk-store-name | Name of the `DiskStore` used to overflow and persist
queue events. queued events.
| geode.gateway-sender.<id>.disk-synchronous | Indicates whether disk writes are synchronous or asynchronous. | geode.gateway-sender.<id>.disk-synchronous | Indicates whether disk writes are synchronous
or asynchronous.
| geode.gateway-sender.<id>.dispatcher-threads | Number of threads used to dispatch events. | geode.gateway-sender.<id>.dispatcher-threads | Number of threads used to dispatch events.
| geode.gateway-sender.<id>.max-parallelism-for-replicated-region |
| geode.gateway-sender.<id>.max-queue-memory | Maximum amount of memory (MB) usable for this | geode.gateway-sender.<id>.max-queue-memory | Maximum amount of memory (MB) usable for this
`GatewaySender` instance's queue. `GatewaySender` instance's queue.
| geode.gateway-sender.<id>.max-parallelism-for-replicated-region |
| geode.gateway-sender.<id>.order-policy | Order policy followed while dispatching the events | geode.gateway-sender.<id>.order-policy | Order policy followed while dispatching the events
to `GatewayReceiver` instances. to `GatewayReceiver` instances.
| geode.gateway-sender.<id>.parallel | Indicates whether this `GatewaySender` is parallel | geode.gateway-sender.<id>.parallel | Indicates whether this `GatewaySender` is parallel
(higher throughput) or serial. (higher throughput) or serial.
| geode.gateway-sender.<id>.paused | Indicates whether this `GatewaySender` is paused. | geode.gateway-sender.<id>.paused | Indicates whether this `GatewaySender` is paused.
| geode.gateway-sender.<id>.persistent | Indicates whether this `GatewaySender` persists queue | geode.gateway-sender.<id>.persistent | Indicates whether this `GatewaySender` persists
events to disk. queue events to disk.
| geode.gateway-sender.<id>.remote-distributed-system-id | Identifier for the remote distributed system. | geode.gateway-sender.<id>.remote-distributed-system-id | Identifier for the remote distributed system.
| geode.gateway-sender.<id>.running | Indicates whether this `GatewaySender` | geode.gateway-sender.<id>.running | Indicates whether this `GatewaySender`
is currently running. is currently running.
| geode.gateway-sender.<id>.socket-buffer-size | Configured buffer size for the socket connections | geode.gateway-sender.<id>.socket-buffer-size | Configured buffer size for the socket connections
between this `GatewaySender` and its receiving `GatewayReceiver`. between this `GatewaySender` and the receiving `GatewayReceiver`.
| geode.gateway-sender.<id>.socket-read-timeout | Amount of time (ms) that a socket read between | geode.gateway-sender.<id>.socket-read-timeout | Amount of time (ms) that a socket read between this
this sending `GatewaySender` and its receiving `GatewayReceiver` blocks. sending `GatewaySender` and the receiving `GatewayReceiver` blocks.
|===================================================================================================================== |=====================================================================================================================

View File

@@ -39,8 +39,8 @@ public class MySpringBootApplication {
---- ----
==== ====
You can disable more than one auto-configuration class at a time by specifying each class You can disable more than one auto-configuration class at a time by specifying each class in the `exclude` attribute
in the `exclude` attribute using array syntax: using array syntax:
.Disable Auto-configuration of PDX & SSL .Disable Auto-configuration of PDX & SSL
==== ====
@@ -78,24 +78,28 @@ The current set of auto-configuration classes in Spring Boot for {geode-name} in
* `SslAutoConfiguration` * `SslAutoConfiguration`
[[geode-gemfire-switch]] [[geode-gemfire-switch]]
=== Switching from {geode-name} to Pivotal GemFire or Pivotal Cloud Cache (PCC) === Switching from {geode-name} to {pivotal-gemfire-name} or {pivotal-cloudcache-name}
Spring Boot for {geode-name} (SBDG) stopped providing support for {pivotal-gemfire-name} after SBDG 1.3. SBDG 1.3 was
the last version to support both {geode-name} and {pivotal-gemfire-name}. If you need support for {pivotal-gemfire-name}
in Spring Boot, then you will need to downgrade to SBDG 1.3.
WARNING: This section is now deprecated. Spring Boot for {geode-name} (SBDG) no longer provides the WARNING: This section is now deprecated. Spring Boot for {geode-name} (SBDG) no longer provides the
`spring-gemfire-starter` and related starter modules. As of SBDG 1.4, SBDG is based on {geode-name} 1.13. Standalone `spring-gemfire-starter` or related starter modules. As of SBDG 1.4, SBDG is based on {geode-name} 1.13. Standalone
GemFire bits based on {geode-name} are no longer being released by VMware, Inc. after GemFire 9.10. GemFire 9.10 was GemFire bits based on {geode-name} are no longer being released by VMware, Inc. after GemFire 9.10. GemFire 9.10
based on {geode-name} 1.12, and SBDG can no longer properly support standalone GemFire bits (version <= 9.10). was based on {geode-name} 1.12, and SBDG can no longer properly support standalone GemFire bits (version <= 9.10).
NOTE: What was Pivotal GemFire has now been rebranded as {pivotal-gemfire-website}[VMware Tanzu GemFire] and what NOTE: What was Pivotal GemFire has now been rebranded as {pivotal-gemfire-website}[{pivotal-gemfire-name}]
was Pivotal Cloud Cache (PCC) running on Pivotal CloudFoundry (PCF) has been rebranded as and what was Pivotal Cloud Cache (PCC) running on Pivotal CloudFoundry (PCF) has been rebranded as
{pivotal-cloudcache-website}[VMware Tanzu GemFire for VMs] {pivotal-cloudcache-website}[{pivotal-cloudcache-name}] and {pivotal-cloudfoundry-website}[{pivotal-cloudfoundry-name} (TAS)],
and {pivotal-cloudfoundry-website}[VMware Tanzu Application Service (TAS)], respectively. respectively.
[[geode-cluster-configuration-bootstrapping]] [[geode-cluster-configuration-bootstrapping]]
=== Running an {geode-name} Cluster with Spring Boot from Your IDE === Running an {geode-name} cluster with Spring Boot from your IDE
As described in <<geode-clientcache-applications>>, you can configure and run a small {geode-name} cluster As described in <<geode-clientcache-applications>>, you can configure and run a small {geode-name} cluster from inside
from inside your IDE using Spring Boot. This is extremely helpful during development, since it you manually your IDE using Spring Boot. This is extremely helpful during development because it enables you to manually run, test,
spin up, test, and debug your applications quickly and easily. and debug your applications quickly and easily.
Spring Boot for {geode-name} includes such a class: Spring Boot for {geode-name} includes such a class:
@@ -108,23 +112,23 @@ include::{docs-src-dir}/org/springframework/geode/docs/example/app/server/Spring
==== ====
This class is a proper Spring Boot application that you can use to configure and bootstrap multiple {geode-name} servers This class is a proper Spring Boot application that you can use to configure and bootstrap multiple {geode-name} servers
and join them together to form a small cluster by modifying the runtime configuration of this class ever so and join them together to form a small cluster. You only need to modify the runtime configuration of this class
slightly. to startup multiple servers.
Initially, you probably want to start a single (primary) server with the embedded locator and manager service. Initially, you will need to start a single (primary) server with an embedded Locator and Manager.
The locator service enables members in the cluster to locate one another and lets new members try to The Locator enables members in the cluster to locate one another and lets new members join the cluster as a peer.
join the cluster as a peer. The locator service also lets clients connect to the servers The Locator also lets clients connect to the servers in the cluster. When the cache client's connection pool
in the cluster. When the cache client's pool is configured to use locators, the pool can intelligently is configured to use Locators, the pool of connections can intelligently route data requests directly to the server
route data requests directly to the server hosting the data (a.k.a. single-hop access), especially when the data hosting the data (a.k.a. single-hop access), especially when the data is partitioned/sharded across multiple servers
is partitioned/sharded across servers in the cluster. Locator pools include support for load balancing connections in the cluster. Locator-based connection pools include support for load balancing connections and handling automatic
and handling automatic fail-over in the event of failed connections, among other things. fail-over in the event of failed connections, among other things.
The manager service lets you connect to this server using Gfsh (the {geode-name} The Manager lets you connect to this server using Gfsh ({geode-name}'s
{apache-geode-docs}/tools_modules/gfsh/chapter_overview.html[command-line shell tool]). {apache-geode-docs}/tools_modules/gfsh/chapter_overview.html[command-line shell tool]).
To start your primary server, create a run configuration in your IDE for the `SpringBootApacheGeodeCacheServerApplication` To start your primary server, create a run configuration in your IDE for the `SpringBootApacheGeodeCacheServerApplication`
class with the following, recommended JRE command-line options: class using the following, recommended JRE command-line options:
.Server 1 run profile configuration .Server 1 run profile configuration
==== ====
@@ -134,7 +138,7 @@ class with the following, recommended JRE command-line options:
---- ----
==== ====
Start the class. You should see output similar to the following: Run the class. You should see output similar to the following:
.Server 1 output on startup .Server 1 output on startup
==== ====
@@ -304,22 +308,22 @@ Client Connections : 0
---- ----
==== ====
Now you can start some additional servers to scale-out your cluster. Now you can run additional servers to scale-out your cluster.
To do so, you need to vary the name of the members you add to your cluster as peers. {geode-name} requires To do so, you must vary the name of the members you add to your cluster as peers. {geode-name} requires members in a
that the members in a cluster be named, and the names of each member in the cluster be unique. cluster to be named and for the names of each member in the cluster to be unique.
Additionally, since we are running multiple instances of our `SpringBootApacheGeodeCacheServerApplication` class, Additionally, since we are running multiple instances of our `SpringBootApacheGeodeCacheServerApplication` class,
which also embeds a `CacheServer` instance enabling cache clients to connect, we need to be careful to vary our which also embeds a `CacheServer` component enabling cache clients to connect. Therefore, you must vary the ports
ports used by the embedded services. used by the embedded services.
Fortunately, we do not need to run another embedded locator or manager service (we need only one in this case). Fortunately, you do not need to run another embedded Locator or Manager (you need only one of each in this case).
Therefore, we can switch profiles from non-clustered to using the Spring `clustered` profile, which includes different Therefore, you can switch profiles from non-clustered to using the Spring "clustered" profile, which includes different
configuration (the `ClusterConfiguration` class) to connect another server as a peer member in the cluster, configuration (the `ClusterConfiguration` class) to connect another server as a peer member in the cluster,
which currently has only one member, as shown in the `list members` Gfsh command output (shown earlier). which currently has only one member, as shown in Gfsh with the `list members` command (shown earlier).
To add another server, set the member name and the `CacheServer` port to a different number with the following To add another server, set the member name and `CacheServer` port to different values with the following
run profile configuration: run configuration:
.Run profile configuration for server 2 .Run profile configuration for server 2
==== ====
@@ -329,36 +333,36 @@ run profile configuration:
---- ----
==== ====
Notice that we explicitly activated the `clustered` Spring profile, which enables the configuration provided Notice that we explicitly activated the "clustered" Spring profile, which enables the configuration provided in
in the nested `ClusteredConfiguration` class while disabling the `LonerConfiguration` class. the nested `ClusteredConfiguration` class while disabling the configuration provided in the `LonerConfiguration` class.
This `ClusteredConfiguration` class is also annotated with `@UseLocators`, which sets the {geode-name} `locators` The `ClusteredConfiguration` class is also annotated with `@UseLocators`, which sets the {geode-name} `locators`
property to `localhost[10334]`. By default, it assumes that the locator process/service runs on locahost, property to "localhost[10334]". By default, it assumes that the Locator runs on localhost, listening on the default
listening on the default locator port of 10334. You can adjust your locators endpoint if your locators Locator port of 10334. You can adjust your `locators` connection endpoint if your Locators run elsewhere in your network
run elsewhere in your network by using the `locators` attribute of the `@UseLocators` annotation. by using the `locators` attribute of the `@UseLocators` annotation.
TIP: It is common in production environments to run multiple locators as a separate process. Running multiple locators TIP: In production environments, it is common to run multiple Locators in separate processes. Running multiple Locators
provides redundancy in case a Locator process fails. If all locator processes in your network fail, provides redundancy in case a Locator fails. If all Locators in your cluster fail, then your cluster will continue to
your cluster does not go down. It means that no other members can join the cluster, letting you run, but no other members will be able to join the cluster, which is important when scaling out the cluster. Clients
scale out your cluster. Any clients also cannot connect. Restart the Locators if this happens. also will not be able to connect. Restart the Locators if this happens.
Also, we set the `spring.data.gemfire.name` property to `ServerTwo`, adjusting the name of our member Also, we set the `spring.data.gemfire.name` property to `ServerTwo`, adjusting the name of our member when it joins
when it joins the cluster as a peer. the cluster as a peer.
Finally, we set the `spring.data.gemfire.cache.server.port` to `41414` to vary the `CacheServer` port Finally, we set the `spring.data.gemfire.cache.server.port` property to `41414` to vary the `CacheServer` port used by
used by `ServerTwo`. The default `CacheServer` port is `40404`. If we had not set this property before starting `ServerTwo`. The default `CacheServer` port is `40404`. If we had not set this property before starting `ServerTwo`,
`ServerTwo`, we would have hit a `java.net.BindException`. we would have encounter a `java.net.BindException`.
TIP: Both the `spring.data.gemfire.name` and `spring.data.gemfire.cache.server.port` properties are well-known properties TIP: Both `spring.data.gemfire.name` and `spring.data.gemfire.cache.server.port` are well-known properties used by SDG
used by SDG to dynamically configure {geode-name} with a Spring Boot `application.properties` file to dynamically configure {geode-name} with a Spring Boot `application.properties` file or by using Java System
or Java System properties. You can find these properties in the annotation Javadoc in SDG's annotation-based properties. You can find these properties in the annotation Javadoc in SDG's annotation-based configuration model.
configuration model. For example, see the Javadoc for the For example, see the Javadoc for the
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/CacheServerApplication.html#port--[`spring.data.gemfire.cache.server.port` property]. {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/CacheServerApplication.html#port--[`spring.data.gemfire.cache.server.port` property].
Most of the SDG annotations include corresponding properties that can be defined in `application.properties` Most SDG annotations include corresponding properties that can be defined in Spring Boot `application.properties`,
and is explained in more detail {spring-data-geode-docs-html}/#bootstrap-annotation-config-properties[documentation]. which is explained in detail in the {spring-data-geode-docs-html}/#bootstrap-annotation-config-properties[documentation].
After starting our second server, `ServerTwo`, we should see output similar to the following at the command-line and in Gfsh After starting our second server, `ServerTwo`, we should see output similar to the following at the command-line
when we again `list members` and `describe member`: and in Gfsh when we again `list members` and `describe member`:
.Gfsh output after starting server 2 .Gfsh output after starting server 2
==== ====
@@ -392,8 +396,8 @@ Client Connections : 0
---- ----
==== ====
When we list members, we see `ServerTwo`, and, when we `describe` `ServerTwo`, we see that its `CacheServer` port When we list the members of the cluster, we see `ServerTwo`, and when we `describe` `ServerTwo`, we see that its
is appropriately set to `41414`. `CacheServer` port is appropriately set to `41414`.
We can add one more server, `ServerThree`, by using the following run configuration: We can add one more server, `ServerThree`, by using the following run configuration:
@@ -440,26 +444,26 @@ Client Connections : 0
---- ----
==== ====
Congratulations. You have started a small {geode-name} cluster, with 3 members, by using Spring Boot from inside your IDE. Congratulations. You have just started a small {geode-name} cluster with 3 members by using Spring Boot from inside
your IDE.
You can build and run a Spring Boot, {geode-name} `ClientCache` application that connects to this cluster. Now you can build and run a Spring Boot, {geode-name} `ClientCache` application that connects to this cluster. To do so,
To do so, include and use Spring Boot for {geode-name}. include and use Spring Boot for {geode-name}.
[[geode-testing-support]] [[geode-testing-support]]
=== Testing === Testing
https://github.com/spring-projects/spring-test-data-geode[Spring Test for {geode-name}] is a new, soon-to-be-released https://github.com/spring-projects/spring-test-data-geode[Spring Test for {geode-name}] (STDG) is a relatively new project
and upcoming project to help you write both unit and integration tests when you use {geode-name} in a Spring to help you write both unit and integration tests when you use {geode-name} in a Spring context. In fact, the entire
context. {github-url}/tree/master/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure[test suite]
In fact, the entire {github-url}/tree/master/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure[test suite]
in Spring Boot for {geode-name} is based on this project. in Spring Boot for {geode-name} is based on this project.
All Spring projects that integrate with {geode-name} will use this new test framework for all their testing needs, making All Spring projects that integrate with {geode-name} will use this new test framework for all their testing needs,
this new test framework for {geode-name} a proven and reliable solution for all your {geode-name} application testing making this new test framework for {geode-name} a proven and reliable solution for all your {geode-name} application
needs when using Spring as well. testing needs when using Spring as well.
In future versions, this reference guide will include an entire chapter on testing. In future versions, this reference guide will include an entire chapter on testing along with samples. In the meantime,
look to the STDG https://github.com/spring-projects/spring-test-data-geode#stdg-in-a-nutshell[README].
[[geode-examples]] [[geode-examples]]
=== Examples === Examples
@@ -467,15 +471,14 @@ In future versions, this reference guide will include an entire chapter on testi
The definitive source of truth on how to best use Spring Boot for {geode-name} is to refer to The definitive source of truth on how to best use Spring Boot for {geode-name} is to refer to
the <<geode-samples,samples>>. the <<geode-samples,samples>>.
See also the https://github.com/jxblum/temperature-service[Temperature Service], Spring Boot See also the https://github.com/jxblum/temperature-service[Temperature Service], Spring Boot application that implements
application that implements a temperature sensor and monitoring, internet of things (IOT) example. The example uses SBDG a temperature sensor and monitoring, Internet of Things (IOT) example. The example uses SBDG to showcase {geode-name} CQ,
to showcase {geode-name} CQ, function implementations and executions, and positions {geode-name} as a caching provider function implementations and executions, and positions {geode-name} as a caching provider in Spring's Cache Abstraction.
in Spring's cache abstraction. It is a working, sophisticated, and complete example, and we highly recommend it as a good It is a working, sophisticated, and complete example, and we highly recommend it as a good starting point for real-world
starting point for real-world use cases. use cases.
See the https://github.com/jxblum/contacts-application/tree/master/boot-example[Boot example] See the https://github.com/jxblum/contacts-application/tree/master/boot-example[Boot example] from the contact
from the contact application reference implementation (RI) for Spring Data for {geode-name} (SDG) as yet another application reference implementation (RI) for Spring Data for {geode-name} (SDG) as yet another example.
example.
[[references]] [[references]]
=== References === References

View File

@@ -3,25 +3,26 @@
:gemfire-name: {pivotal-gemfire-name} :gemfire-name: {pivotal-gemfire-name}
:geode-name: {apache-geode-name} :geode-name: {apache-geode-name}
One of the easiest, quickest and least invasive ways to start using {geode-name} in your Spring Boot applications One of the easiest, quickest and least invasive ways to start using {geode-name} in your Spring Boot applications
is to use {geode-name} as a {spring-framework-docs}/integration.html#cache-store-configuration[caching provider] is to use {geode-name} as a {spring-framework-docs}/integration.html#cache-store-configuration[caching provider]
in {spring-framework-docs}/integration.html#cache[Spring's cache abstraction]. SDG in {spring-framework-docs}/integration.html#cache[Spring's Cache Abstraction]. SDG
{spring-framework-docs}/integration.html#cache-store-configuration-gemfire[enables] {spring-framework-docs}/integration.html#cache-store-configuration-gemfire[enables]
{geode-name} to function as a caching provider in Spring's cache abstraction. {geode-name} to function as a caching provider in Spring's Cache Abstraction.
TIP: See the _Spring Data for {geode-name} Reference Guide_ for more details on the TIP: See the _Spring Data for {geode-name} Reference Guide_ for more details on the
{spring-data-geode-docs-html}/#apis:spring-cache-abstraction[support] and {spring-data-geode-docs-html}/#bootstrap-annotation-config-caching[configuration] {spring-data-geode-docs-html}/#apis:spring-cache-abstraction[support] and {spring-data-geode-docs-html}/#bootstrap-annotation-config-caching[configuration]
of {geode-name} as a caching provider in Spring's cache abstraction. of {geode-name} as a caching provider in Spring's Cache Abstraction.
TIP: Make sure you thoroughly understand the {spring-framework-docs}/integration.html#cache-strategies[concepts] TIP: Make sure you thoroughly understand the {spring-framework-docs}/integration.html#cache-strategies[concepts]
behind Spring's cache abstraction before you continue. behind Spring's cache abstraction before you continue.
TIP: See also the relevant section on {spring-boot-docs-html}/#boot-features-caching[caching] TIP: See also the relevant section on {spring-boot-docs-html}/#boot-features-caching[caching]
in Spring Boot's reference documentation. Spring Boot even provides auto-configuration support for a few in Spring Boot's reference documentation. Spring Boot even provides auto-configuration support for a few of the simple
simple {spring-boot-docs-html}/#_supported_cache_providers[caching providers]. {spring-boot-docs-html}/#_supported_cache_providers[caching providers].
Indeed, caching can be an effective software design pattern to avoid the cost of invoking Indeed, caching can be an effective software design pattern to avoid the cost of invoking a potentially expensive
a potentially expensive operation when, given the same input, the operation yields the same output every time. operation when, given the same input, the operation yields the same output, every time.
Some classic examples of caching include, but are not limited to, looking up a customer by name or account number, Some classic examples of caching include, but are not limited to, looking up a customer by name or account number,
looking up a book by ISBN, geocoding a physical address, and caching the calculation of a person's credit score looking up a book by ISBN, geocoding a physical address, and caching the calculation of a person's credit score
@@ -32,16 +33,15 @@ low latency, and multi-site (WAN) capabilities, then you should consider https:/
Alternatively, VMWare, Inc. offers a commercial solution, built on {geode-name}, called {gemfire-name}. Alternatively, VMWare, Inc. offers a commercial solution, built on {geode-name}, called {gemfire-name}.
Spring's {spring-framework-docs}/integration.html#cache-annotations[declarative, annotation-based caching] makes it Spring's {spring-framework-docs}/integration.html#cache-annotations[declarative, annotation-based caching] makes it
simple to get started with caching, which is as easy as annotating your application components with simple to get started with caching, which is as easy as annotating your application components with the appropriate
the appropriate Spring cache annotations. Spring cache annotations.
TIP: Spring's declarative, annotation-based caching also {spring-framework-docs}/integration.html#cache-jsr-107[supports] TIP: Spring's declarative, annotation-based caching also {spring-framework-docs}/integration.html#cache-jsr-107[supports]
JCache (JSR-107) annotations. JCache (JSR-107) annotations.
For example, suppose you want to cache the results of determining a person's eligibility when applying for a For example, suppose you want to cache the results of determining a person's eligibility when applying for a loan. A
loan. A person's financial status is unlikely to change in the time that the computer runs the algorithms to compute person's financial status is unlikely to change in the time that the computer runs the algorithms to compute a person's
a person's eligibility after all the financial information for the person has been collected and submitted for review eligibility after all the financial information for the person has been collected, submitted for review and processed.
and processing.
Our application might consist of a financial loan service to process a person's eligibility over a given period of time: Our application might consist of a financial loan service to process a person's eligibility over a given period of time:
@@ -63,7 +63,7 @@ class FinancialLoanApplicationService {
Notice the `@Cacheable` annotation declared on the `processEligibility(:Person, :Timespan)` method of our service class. Notice the `@Cacheable` annotation declared on the `processEligibility(:Person, :Timespan)` method of our service class.
When the `FinancialLoanApplicationService.processEligibility(..)` method is called, Spring's caching infrastructure When the `FinancialLoanApplicationService.processEligibility(..)` method is called, Spring's caching infrastructure
first consults the `EligibilityDecisions` cache to determine if a decision has already been computed for the given first consults the "EligibilityDecisions" cache to determine if a decision has already been computed for the given
person within the given span of time. If the person's eligibility in the given time frame has already been determined, person within the given span of time. If the person's eligibility in the given time frame has already been determined,
the existing decision is returned from the cache. Otherwise, the `processEligibility(..)` method is invoked the existing decision is returned from the cache. Otherwise, the `processEligibility(..)` method is invoked
and the result of the method is cached when the method returns, before returning the decision to the caller. and the result of the method is cached when the method returns, before returning the decision to the caller.
@@ -71,22 +71,22 @@ and the result of the method is cached when the method returns, before returning
Spring Boot for {geode-name} auto-configures {geode-name} as the caching provider when {geode-name} is declared on Spring Boot for {geode-name} auto-configures {geode-name} as the caching provider when {geode-name} is declared on
the application classpath and when no other caching provider (such as Redis) has been configured. the application classpath and when no other caching provider (such as Redis) has been configured.
If Spring Boot for {geode-name} detects that another cache provider has already been configured, {geode-name} If Spring Boot for {geode-name} detects that another cache provider has already been configured, then {geode-name}
does not function as the caching provider for the application. This lets you configure another store, such as will not function as the caching provider for the application. This lets you configure another store, such as
Redis, as the caching provider and perhaps use {geode-name} as your application's persistent store. Redis, as the caching provider and perhaps use {geode-name} as your application's persistent store.
The only other requirement to enable caching in a Spring Boot application is for the declared caches (as specified The only other requirement to enable caching in a Spring Boot application is for the declared caches (as specified
in Spring's or JSR-107's caching annotations) to have been created and already exist, especially before the operation in Spring's or JSR-107's caching annotations) to have been created and already exist, especially before the operation
on which caching has been applied is invoked. This means the backend data store must provide the data structure on which caching was applied is invoked. This means the backend data store must provide the data structure that serves
that serves as the cache. For {geode-name}, this means a cache `Region`. as the cache. For {geode-name}, this means a cache `Region`.
To configure the necessary regions that back the caches declared in Spring's cache annotations, To configure the necessary Regions that back the caches declared in Spring's cache annotations, use Spring Data
use Spring Data for {geode-name}'s for {geode-name}'s {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegions.html[`@EnableCachingDefinedRegions`]
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegions.html[`@EnableCachingDefinedRegions`]
annotation. annotation.
The following listing shows a complete Spring Boot application: The following listing shows a complete Spring Boot application:
.Spring Boot cache enabled application using {geode-name}
==== ====
[source,java] [source,java]
---- ----
@@ -106,8 +106,8 @@ class FinancialLoanApplication {
TIP: The `FinancialLoanApplicationService` is picked up by Spring's classpath component scan, since this class TIP: The `FinancialLoanApplicationService` is picked up by Spring's classpath component scan, since this class
is annotated with Spring's `@Service` stereotype annotation. is annotated with Spring's `@Service` stereotype annotation.
TIP: You can set the `DataPolicy` of the region created through the `@EnableCachingDefinedRegions` annotation by TIP: You can set the `DataPolicy` of the Region created through the `@EnableCachingDefinedRegions` annotation
setting the `clientRegionShortcut` to a valid enumerated value. by setting the `clientRegionShortcut` attribute to a valid enumerated value.
NOTE: Spring Boot for {geode-name} does not recognize nor apply the `spring.cache.cache-names` property. Instead, you NOTE: Spring Boot for {geode-name} does not recognize nor apply the `spring.cache.cache-names` property. Instead, you
should use SDG's `@EnableCachingDefinedRegions` on an appropriate Spring Boot application `@Configuration` class. should use SDG's `@EnableCachingDefinedRegions` on an appropriate Spring Boot application `@Configuration` class.
@@ -120,43 +120,44 @@ needs:
* Look-aside caching * Look-aside caching
* Near caching * Near caching
* Inline caching * [Async] Inline caching
* Multi-site caching * Multi-site caching
Typically, when most users think of caching, they think of look-aside caching. This is the default caching Typically, when most users think of caching, they think of Look-aside caching. This is the default caching
pattern applied by Spring's cache abstraction. pattern applied by Spring's Cache Abstraction.
In a nutshell, near caching keeps the data closer to where the data is used, thereby improving on performance due to In a nutshell, Near caching keeps the data closer to where the data is used, thereby improving on performance due to
lower latencies when data is needed (no extra network hops). This also improves application throughput -- that is, the lower latencies when data is needed (no extra network hops). This also improves application throughput -- that is,
amount of work completed in a given period of time. the amount of work completed in a given period of time.
Within inline caching_, developers have a choice between synchronous (read/write-through) and asynchronous Within Inline caching_, developers have a choice between synchronous (read/write-through) and asynchronous (write-behind)
(write-behind_) configurations depending on the application use case and requirements. Synchronous, read/write-through configurations depending on the application use case and requirements. Synchronous, read/write-through Inline caching
inline caching is necessary if consistency is a concern. Asynchronous, write-behind inline caching is applicable is necessary if consistency is a concern. Asynchronous, write-behind Inline caching is applicable if throughput
if throughput and low-latency are a priority. and low-latency are a priority.
Within multi-site caching, there are active-passive and active-active arrangements. More details on multi-site Within Multi-site caching, there are active-active and active-passive arrangements. More details on Multi-site caching
caching will be presented in a later release. will be presented in a later release.
[[geode-caching-provider-look-aside-caching]] [[geode-caching-provider-look-aside-caching]]
==== Look-Aside Caching ==== Look-Aside Caching
TIP: See the corresponding sample link:guides/caching-look-aside.html[Guide] and {github-samples-url}/caching/look-aside[code] TIP: See the corresponding sample link:guides/caching-look-aside.html[guide] and {github-samples-url}/caching/look-aside[code]
to see look-aside caching with {apache-geode-name} in action. to see Look-aside caching with {apache-geode-name} in action.
The caching pattern demonstrated in the preceding example is a form of The caching pattern demonstrated in the preceding example is a form of
https://content.pivotal.io/blog/an-introduction-to-look-aside-vs-inline-caching-patterns[look-aside caching]. https://content.pivotal.io/blog/an-introduction-to-look-aside-vs-inline-caching-patterns[Look-aside caching]
(or "_Cache Aside_").
Essentially, the data of interest is searched for in the cache first, before calling a potentially expensive Essentially, the data of interest is searched for in the cache first, before calling a potentially expensive
operation, such as an operation that makes an IO- or network-bound request that results in either a blocking operation, such as an operation that makes an IO- or network-bound request that results in either a blocking
or a latency-sensitive computation. or a latency-sensitive computation.
If the data can be found in the cache (stored in-memory to reduce latency), the data is returned without ever If the data can be found in the cache (stored in-memory to reduce latency), the data is returned without ever invoking
invoking the expensive operation. If the data cannot be found in the cache, the operation must be invoked. the expensive operation. If the data cannot be found in the cache, the operation must be invoked. However, before
However, before returning, the result of the operation is cached for subsequent requests when the the same input returning, the result of the operation is cached for subsequent requests when the same input is requested again by
is requested again by another caller, resulting in much improved response times. another caller, resulting in much improved response times.
The typical look-aside caching pattern applied in your application code looks similar to the following: The typical Look-aside caching pattern applied in your Spring application code looks similar to the following:
.Look-Aside Caching Pattern Applied .Look-Aside Caching Pattern Applied
==== ====
@@ -183,37 +184,36 @@ class CustomerService {
==== ====
In this design, the `CustomerRepository` is perhaps a JDBC- or JPA/Hibernate-backed implementation that accesses In this design, the `CustomerRepository` is perhaps a JDBC- or JPA/Hibernate-backed implementation that accesses
the external data source (the RDBMS) directly. The `@Cacheable` annotation wraps, or "`decorates`", the external data source (for example, an RDBMS) directly. The `@Cacheable` annotation wraps, or "decorates",
the `findByAccount(:Account):Customer` operation to provide caching facilities. the `findByAccount(:Account):Customer` operation (method) to provide caching behavior.
NOTE: This operation may be expensive, because it might validate the customer's account before looking up the customer, NOTE: This operation may be expensive because it may validate the customer's account before looking up the customer,
pull multiple bits of information to retrieve the customer record, and so on -- hence the need for caching. pull multiple bits of information to retrieve the customer record, and so on -- hence the need for caching.
[[geode-caching-provider-near-caching]] [[geode-caching-provider-near-caching]]
==== Near Caching ==== Near Caching
TIP: See the corresponding sample link:guides/caching-near.html[guide] and {github-samples-url}/caching/near[code] TIP: See the corresponding sample link:guides/caching-near.html[guide] and {github-samples-url}/caching/near[code]
to see near caching with {apache-geode-name} in action. to see Near caching with {apache-geode-name} in action.
Near caching is another pattern of caching where the cache is collocated with the application. This is useful when Near caching is another pattern of caching where the cache is collocated with the application. This is useful when
the caching technology is configured in a client/server arrangement. the caching technology is configured in a client/server arrangement.
We already mentioned that Spring Boot for {geode-name} <<clientcache-applications.adoc#geode-clientcache-applications, provides>> We already mentioned that Spring Boot for {geode-name} <<clientcache-applications.adoc#geode-clientcache-applications, provides>>
an auto-configured `ClientCache` instance by default. A `ClientCache` instance is most effective an auto-configured `ClientCache` instance by default. A `ClientCache` instance is most effective when the data access
when the data access operations, including cache access, are distributed to the servers in a cluster that is accessible to the operations, including cache access, are distributed to the servers in a cluster that is accessible to the client and,
client and, in most cases, multiple clients. This lets other cache client applications access the same data. in most cases, multiple clients. This lets other cache client applications access the same data. However, this also
However, this also means the application incurs a network hop penalty to evaluate the presence of the data means the application incurs a network hop penalty to evaluate the presence of the data in the cache.
in the cache.
To help avoid the cost of this network hop in a client/server topology, a local cache can be established to To help avoid the cost of this network hop in a client/server topology, a local cache can be established to maintain
maintain a subset of the data in the corresponding server-side cache (that is, a region). Therefore, the client cache a subset of the data in the corresponding server-side cache (that is, a Region). Therefore, the client cache contains
contains only the data of interest to the application. This "`local`" cache (that is, a client-side region) is consulted only the data of interest to the application. This "local" cache (that is, a client-side Region) is consulted before
before forwarding the lookup request to the server. forwarding the lookup request to the server.
To enable near caching when using either {geode-name}, change the region's (that is the `Cache` in Spring's To enable Near caching when using {geode-name}, change the Region's (that is the `Cache` in Spring's Cache Abstraction)
cache abstraction) data management policy from `PROXY` (the default) to `CACHING_PROXY`: data management policy from `PROXY` (the default) to `CACHING_PROXY`:
.Enabling Near Caching using {geode-name} .Enable Near Caching with {geode-name}
==== ====
[source,java] [source,java]
---- ----
@@ -228,59 +228,59 @@ class FinancialLoanApplication {
---- ----
==== ====
TIP: The default client region data management policy is TIP: The default client Region data management policy is
{apache-geode-javadoc}/org/apache/geode/cache/client/ClientRegionShortcut.html#PROXY[`ClientRegionShortcut.PROXY`]. {apache-geode-javadoc}/org/apache/geode/cache/client/ClientRegionShortcut.html#PROXY[`ClientRegionShortcut.PROXY`].
As a result, all data access operations are immediately forwarded to the server. As a result, all data access operations are immediately forwarded to the server.
TIP: See also the {geode-name} documentation concerning TIP: See also the {geode-name} documentation concerning
{apache-geode-docs}/developing/events/how_client_server_distribution_works.html[client/server event distribution] {apache-geode-docs}/developing/events/how_client_server_distribution_works.html[client/server event distribution]
and, specifically, "`Client Interest Registration on the Server,`" which applies when you use client `CACHING_PROXY` regions to manage state and, specifically, "`Client Interest Registration on the Server,`" which applies when you use client `CACHING_PROXY`
in addition to the corresponding server-side region. This is necessary to receive updates on entries in the region Regions to manage state in addition to the corresponding server-side Region. This is necessary to receive updates on
that might have been changed by other clients that have access to the same data. entries in the Region that might have been changed by other clients that have access to the same data.
[[geode-caching-provider-inline-caching]] [[geode-caching-provider-inline-caching]]
==== Inline Caching ==== Inline Caching
The next pattern of caching covered in this chapter is inline caching. The next pattern of caching covered in this chapter is Inline caching.
You can apply two different configurations of inline caching to your Spring Boot applications You can apply two different configurations of Inline caching to your Spring Boot applications when you use
when you use the inline caching pattern: synchronous (read/write-through) and asynchronous (write-behind). the Inline caching pattern: synchronous (read/write-through) and asynchronous (write-behind).
NOTE: Asynchronous (currently) offers only write capabilities, from the cache to the external data source. NOTE: Asynchronous (currently) offers only write capabilities, from the cache to the external data source. There is no
There is no option to asynchronously and automatically load the cache when the value becomes available in the option to asynchronously and automatically load the cache when the value becomes available in the external data source.
external data source.
[[geode-caching-provider-inline-caching-synchronous]] [[geode-caching-provider-inline-caching-synchronous]]
===== Synchronous Inline Caching ===== Synchronous Inline Caching
TIP: See the corresponding sample link:guides/caching-inline.html[guide] and {github-samples-url}/caching/inline[code] TIP: See the corresponding sample link:guides/caching-inline.html[guide] and {github-samples-url}/caching/inline[code]
to see inline caching with {geode-name} in action. to see Inline caching with {geode-name} in action.
When employing inline caching and a cache miss occurs, the application service method may still not be invoked, since When employing Inline caching and a cache miss occurs, the application service method might not be invoked still, since
a cache can be configured to invoke a loader to load the missing entry from an external data source. a cache can be configured to invoke a loader to load the missing entry from an external data source.
With {geode-name}, you can configure the cache (or, to use {geode-name} terminology, the region) with a With {geode-name}, you can configure the cache (or, to use {geode-name} terminology, the Region) with a
{apache-geode-javadoc}/org/apache/geode/cache/CacheLoader.html[`CacheLoader`]. A `CacheLoader` is implemented to retrieve {apache-geode-javadoc}/org/apache/geode/cache/CacheLoader.html[`CacheLoader`]. A `CacheLoader` is implemented to
missing values from an external data source when a cache miss occurs. The external data source could be an RDBMS or any other type of data store (for example, another NoSQL retrieve missing values from an external data source when a cache miss occurs. The external data source could be
data store, such as Apache Cassandra, MongoDB, or Neo4j). an RDBMS or any other type of data store (for example, another NoSQL data store, such as Apache Cassandra, MongoDB,
or Neo4j).
TIP: See the {geode-name} User Guide on TIP: See {geode-name}'s User Guide on
{apache-geode-docs}/developing/outside_data_sources/how_data_loaders_work.html[data loaders] for more details. {apache-geode-docs}/developing/outside_data_sources/how_data_loaders_work.html[data loaders] for more details.
Likewise, you can also configure an {geode-name} region with a Likewise, you can also configure an {geode-name} Region with a
{apache-geode-javadoc}/org/apache/geode/cache/CacheWriter.html[`CacheWriter`]. A `CacheWriter` is responsible for writing {apache-geode-javadoc}/org/apache/geode/cache/CacheWriter.html[`CacheWriter`]. A `CacheWriter` is responsible for
an entry that has been put into the region to the backend data store, such as an RDBMS. This is referred to as a "`write-through`" writing an entry that has been put into the Region to the backend data store, such as an RDBMS. This is referred to
operation, because it is synchronous. If the backend data store fails to be updated, the entry is not stored in as a write-through operation, because it is synchronous. If the backend data store fails to be updated, the entry is
the region. This helps to ensure consistency between the backend data store and the {geode-name} region. not stored in the Region. This helps to ensure consistency between the backend data store and the {geode-name} Region.
TIP: You can also implement inline caching by using asynchronous write-behind operations by registering TIP: You can also implement Inline caching using asynchronous write-behind operations by registering
an {apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventListener.html[`AsyncEventListener`] on an an {apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventListener.html[`AsyncEventListener`]
{apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventQueue.html[`AsyncEventQueue`] attached to a server-side region. on an {apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventQueue.html[`AsyncEventQueue`] attached to
See the {geode-name} User Guide for more a server-side Region. See {geode-name}'s User Guide for more
{apache-geode-docs}/developing/events/implementing_write_behind_event_handler.html[detail]. We cover asynchronous {apache-geode-docs}/developing/events/implementing_write_behind_event_handler.html[details]. We cover asynchronous
write-behind inline caching in the next section. write-behind Inline caching in the next section.
The typical pattern of inline caching when applied to application code looks similar to the following: The typical pattern of Inline caching when applied to application code looks similar to the following:
.Inline Caching Pattern Applied .Inline Caching Pattern Applied
==== ====
@@ -305,18 +305,18 @@ class CustomerService {
---- ----
==== ====
The main difference is that no Spring or JSR-107 caching annotations are applied to the application's service methods The main difference is that no Spring or JSR-107 caching annotations are applied to the application's service methods,
and the `CustomerRepository` accesses {geode-name} directly and NOT the RDBMS. and the `CustomerRepository` accesses {geode-name} directly and the RDBMS indirectly.
[[geode-caching-provider-inline-caching-synchronous-cacheloader-cachewriter]] [[geode-caching-provider-inline-caching-synchronous-cacheloader-cachewriter]]
====== Implementing CacheLoaders and CacheWriters for Inline Caching ====== Implementing CacheLoaders and CacheWriters for Inline Caching
You can use Spring to configure a `CacheLoader` or `CacheWriter` as a bean in the Spring `ApplicationContext` You can use Spring to configure a `CacheLoader` or `CacheWriter` as a bean in the Spring `ApplicationContext` and then
and then wire the loader or writer to a region. Given that the `CacheLoader` or `CacheWriter` is a Spring bean wire the loader or writer to a Region. Given that the `CacheLoader` or `CacheWriter` is a Spring bean like any other
like any other bean in the Spring `ApplicationContext`, you can inject any `DataSource` you like into the loader or writer. bean in the Spring `ApplicationContext`, you can inject any `DataSource` you like into the loader or writer.
While you can configure client regions with `CacheLoaders` and `CacheWriters`, it is more common to While you can configure client Regions with `CacheLoaders` and `CacheWriters`, it is more common to configure
configure the corresponding server-side region: the corresponding server-side Region:
==== ====
[source,java] [source,java]
@@ -331,33 +331,32 @@ class FinancialLoanApplicationServer {
@Bean("EligibilityDecisions") @Bean("EligibilityDecisions")
PartitionedRegionFactoryBean<Object, Object> eligibilityDecisionsRegion( PartitionedRegionFactoryBean<Object, Object> eligibilityDecisionsRegion(
GemFireCache gemfireCache, CacheLoader decisionManagementSystemLoader, GemFireCache gemfireCache, CacheLoader eligibilityDecisionLoader,
CacheWriter decisionManagementSystemWriter) { CacheWriter eligibilityDecisionWriter) {
PartitionedRegionFactoryBean<?, EligibilityDecision> eligibilityDecisionsRegion = PartitionedRegionFactoryBean<?, EligibilityDecision> eligibilityDecisionsRegion =
new PartitionedRegionFactoryBean<>(); new PartitionedRegionFactoryBean<>();
eligibilityDecisionsRegion.setCache(gemfireCache); eligibilityDecisionsRegion.setCache(gemfireCache);
eligibilityDecisionsRegion.setCacheLoader(decisionManagementSystemLoader); eligibilityDecisionsRegion.setCacheLoader(eligibilityDecisionLoader);
eligibilityDecisionsRegion.setCacheWriter(decisionManagementSystemWriter); eligibilityDecisionsRegion.setCacheWriter(eligibilityDecisionWriter);
eligibilityDecisionsRegion.setPersistent(false); eligibilityDecisionsRegion.setPersistent(false);
return eligibilityDecisionsRegion; return eligibilityDecisionsRegion;
} }
@Bean @Bean
CacheLoader<?, EligibilityDecision> decisionManagementSystemLoader( CacheLoader<?, EligibilityDecision> eligibilityDecisionLoader(
DataSource dataSource) { DataSource dataSource) {
return new DecisionManagementSystemLoader(dataSource); return new EligibilityDecisionLoader(dataSource);
} }
@Bean @Bean
CacheWriter<?, EligibilityDecision> decisionManagementSystemWriter( CacheWriter<?, EligibilityDecision> eligibilityDecisionWriter(
DataSource dataSource) { DataSource dataSource) {
return new DecisionManagementSystemWriter(dataSource); return new EligibilityDecisionWriter(dataSource);
} }
@Bean @Bean
@@ -371,24 +370,25 @@ class FinancialLoanApplicationServer {
Then you could implement the {apache-geode-javadoc}/org/apache/geode/cache/CacheLoader.html[`CacheLoader`] Then you could implement the {apache-geode-javadoc}/org/apache/geode/cache/CacheLoader.html[`CacheLoader`]
and {apache-geode-javadoc}/org/apache/geode/cache/CacheWriter.html[`CacheWriter`] interfaces, as appropriate: and {apache-geode-javadoc}/org/apache/geode/cache/CacheWriter.html[`CacheWriter`] interfaces, as appropriate:
.DecisionManagementSystemLoader .EligibilityDecisionLoader
==== ====
[source,java] [source,java]
---- ----
class DecisionManagementSystemLoader implements CacheLoader<?, EligibilityDecision> { class EligibilityDecisionLoader implements CacheLoader<?, EligibilityDecision> {
private final DataSource dataSource; private final DataSource dataSource;
DecisionManagementSystemLoader(DataSource dataSource) { EligibilityDecisionLoader(DataSource dataSource) {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
public EligibilityDecision load(LoadHelper<?, EligibilityDecision> helper) { public EligibilityDecision load(LoadHelper<?, EligibilityDecision> helper) {
Object key = helper.getKey(); Object key = helper.getKey();
// Use the configured DataSource to load the value identified by the key from a backend, external data store. // Use the configured DataSource to load the EligibilityDecision identified by the key
} // from a backend, external data store.
}
} }
---- ----
==== ====
@@ -396,18 +396,18 @@ class DecisionManagementSystemLoader implements CacheLoader<?, EligibilityDecisi
TIP: SBDG provides the `org.springframework.geode.cache.support.CacheLoaderSupport` `@FunctionalInterface` to TIP: SBDG provides the `org.springframework.geode.cache.support.CacheLoaderSupport` `@FunctionalInterface` to
conveniently implement application `CacheLoaders`. conveniently implement application `CacheLoaders`.
If the configured `CacheLoader` still cannot resolve the value, the cache lookup operation results in a miss If the configured `CacheLoader` still cannot resolve the value, the cache lookup operation results in a cache miss
and the application service method is then invoked to compute the value: and the application service method is then invoked to compute the value:
.DecisionManagementSystemWriter .EligibilityDecisionWriter
==== ====
[source,java] [source,java]
---- ----
class DecisionManagementSystemWriter implements CacheWriter<?, EligibilityDecision> { class EligibilityDecisionWriter implements CacheWriter<?, EligibilityDecision> {
private final DataSource dataSource; private final DataSource dataSource;
DecisionManagementSystemWriter(DataSource dataSource) { EligibilityDecisionWriter(DataSource dataSource) {
this.dataSource = dataSource; this.dataSource = dataSource;
} }
@@ -428,42 +428,40 @@ class DecisionManagementSystemWriter implements CacheWriter<?, EligibilityDecisi
---- ----
==== ====
TIP: SBDG provides the `org.springframework.geode.cache.support.CacheWriterSupport` interface to TIP: SBDG provides the `org.springframework.geode.cache.support.CacheWriterSupport` interface to conveniently implement
conveniently implement application `CacheWriters`. application `CacheWriters`.
NOTE: Your `CacheWriter` implementation can use any data access technology to interface with NOTE: Your `CacheWriter` implementation can use any data access technology to interface with your backend data store
your backend data store (for example JDBC, Spring's `JdbcTemplate`, JPA with Hibernate, and others). It is not limited to using only (for example JDBC, Spring's `JdbcTemplate`, JPA with Hibernate, and others). It is not limited to using only a
a `javax.sql.DataSource`. In fact, we present another, more useful and convenient approach to implementing `javax.sql.DataSource`. In fact, we present another, more useful and convenient approach to implementing Inline caching
inline caching in the next section. in the next section.
[[geode-caching-provider-inline-caching-synchronous-using-spring-data-repositories]] [[geode-caching-provider-inline-caching-synchronous-using-spring-data-repositories]]
====== Inline Caching with Spring Data Repositories ====== Inline Caching with Spring Data Repositories
Spring Boot for {geode-name} (SBDG) offers dedicated support to configure inline caching with Spring Data Spring Boot for {geode-name} offers dedicated support to configure Inline caching with Spring Data Repositories.
Repositories.
This is powerful, because it lets you: This is powerful, because it lets you:
* Access any backend data store supported by Spring Data (such as Redis for key-value or other data structures, * Access any backend data store supported by Spring Data (such as Redis for key-value or other distributed data
MongoDB for documents, Neo4j for graphs, Elasticsearch for search, and so on). structures, MongoDB for documents, Neo4j for graphs, Elasticsearch for search, and so on).
* Use complex mapping strategies (such as ORM provided by JPA with Hibernate). * Use complex mapping strategies (such as ORM provided by JPA with Hibernate).
We believe that users should store data where it is most easily accessible. If you access We believe that users should store data where it is most easily accessible. If you access and process documents,
and process documents, then MongoDB, Couchbase, or another document store is probably going to be the most logical then MongoDB, Couchbase, or another document store is probably going to be the most logical choice to manage
choice to manage your application's documents. your application's documents.
However, this does not mean that you have to give up {geode-name} in your application/system architecture. You can use However, this does not mean that you have to give up {geode-name} in your application/system architecture. You can use
each data store for what it is good at. While MongoDB is excellent at handling documents, {geode-name} is a highly each data store for what it is good at. While MongoDB is excellent at handling documents, {geode-name} is a valuable
valuable choice for consistency, high availability, low-latency, high-throughput, multi-site, scale-out application choice for consistency, high-availability/low-latency, high-throughput, multi-site, scale-out application use cases.
use cases.
As such, using {geode-name}'s `CacheLoader` and `CacheWriter` provides a nice integration point between itself As such, using {geode-name}'s `CacheLoader` and `CacheWriter` provides a nice integration point between itself and other
and other data stores to best serve your application's use case and requirements. data stores to best serve your application's use case and requirements.
Suppose you use JPA and Hibernate to access (store and read) data managed in an Oracle Database. Then, you can Suppose you use JPA and Hibernate to access data managed in an Oracle database. Then, you can configure {geode-name} to
configure {geode-name} to read/write-through to the backend Oracle Database when performing cache (Region) operations read/write-through to the backend Oracle database when performing cache (Region) operations by delegating to a
by delegating to a Spring Data JPA Repository. Spring Data JPA Repository.
The configuration might look something like: The configuration might look something like:
@@ -489,36 +487,36 @@ class SpringBootOracleDatabaseApacheGeodeApplication {
SBDG provides the `InlineCachingRegionConfigurer<ENTITY, ID>` interface. SBDG provides the `InlineCachingRegionConfigurer<ENTITY, ID>` interface.
Given a `Predicate` to express the criteria used to match the target region by name and a Spring Data `CrudRepository`, Given a `Predicate` to express the criteria used to match the target Region by name and a Spring Data `CrudRepository`,
the `InlineCachingRegionConfigurer` configure and adapts the Spring Data `CrudRepository` as a `CacheLoader` and the `InlineCachingRegionConfigurer` configures and adapts the Spring Data `CrudRepository` as a `CacheLoader`
`CacheWriter` registered on the region (for example, `Customers`) to enable inline caching functionality. and `CacheWriter` registered on the Region (for example, "Customers") to enable Inline caching functionality.
You need only declare `InlineCachingRegionConfigurer` as a bean in the Spring `ApplicationContext` and make You need only declare `InlineCachingRegionConfigurer` as a bean in the Spring `ApplicationContext` and make
the association between the region (by name) and the appropriate Spring Data `CrudRepository`. the association between the Region (by name) and the appropriate Spring Data `CrudRepository`.
In this example, we used JPA and Spring Data JPA to store and retrieve the data in the cache (region) to and from a backend In this example, we used JPA and Spring Data JPA to store and retrieve data stored in the cache (Region) to and from
database. However, you can inject any Spring Data repository for any data store (Redis, MongoDB, and others) that supports a backend database. However, you can inject any Spring Data Repository for any data store (Redis, MongoDB, and others)
the Spring Data repository abstraction. that supports the Spring Data Repository abstraction.
TIP: If you want only to support one-way data access operations when you use inline caching, you can use either TIP: If you want only to support one-way data access operations when you use Inline caching, you can use either
the `RepositoryCacheLoaderRegionConfigurer` for reads or the `RepositoryCacheWriterRegionConfigurer` for writes, the `RepositoryCacheLoaderRegionConfigurer` for reads or the `RepositoryCacheWriterRegionConfigurer` for writes,
instead of the `InlineCachingRegionConfigurer`, which supports both reads and writes. instead of the `InlineCachingRegionConfigurer`, which supports both reads and writes.
TIP: To see a similar implementation of inline caching with a database (an in-memory HSQLDB database) in action, TIP: To see a similar implementation of Inline caching with a database (an in-memory HSQLDB database) in action, see the
see the https://github.com/spring-projects/spring-boot-data-geode/blob/master/spring-geode/src/test/java/org/springframework/geode/cache/inline/database/InlineCachingWithDatabaseIntegrationTests.java[`InlineCachingWithDatabaseIntegrationTests`] test class https://github.com/spring-projects/spring-boot-data-geode/blob/master/spring-geode/src/test/java/org/springframework/geode/cache/inline/database/InlineCachingWithDatabaseIntegrationTests.java[`InlineCachingWithDatabaseIntegrationTests`]
from the SBDG test suite. A dedicated sample will be provided in a future release. test class from the SBDG test suite. A dedicated sample will be provided in a future release.
[[geode-caching-provider-inline-caching-asynchronous]] [[geode-caching-provider-inline-caching-asynchronous]]
===== Asynchronous Inline Caching ===== Asynchronous Inline Caching
TIP: See the corresponding sample link:guides/caching-inline-async.html[guide] TIP: See the corresponding sample link:guides/caching-inline-async.html[guide]
and {github-samples-url}/caching/inline-async[code] to see asynchronous inline caching with {geode-name} in action. and {github-samples-url}/caching/inline-async[code] to see asynchronous Inline caching with {geode-name} in action.
If consistency between the cache and your external data source is not a concern and you need only write If consistency between the cache and your external data source is not a concern, and you need only write from the cache
from the cache to the backend data store periodically, you can employ asynchronous (write-behind) inline caching. to the backend data store periodically, you can employ asynchronous (write-behind) Inline caching.
As the term, "`write-behind,`" implies, a write to the backend data store is asynchronous and not strictly tied to the As the term, "write-behind", implies, a write to the backend data store is asynchronous and not strictly tied to the
cache operation. As a result, the backend data store is in an "`eventually consistent`" state, since the cache is cache operation. As a result, the backend data store is in an "eventually consistent" state, since the cache is
primarily used by the application at runtime to access and manage data. In this case, the backend data store is used primarily used by the application at runtime to access and manage data. In this case, the backend data store is used
to persist the state of the cache (and that of the application) at periodic intervals. to persist the state of the cache (and that of the application) at periodic intervals.
@@ -533,20 +531,19 @@ batch updates.
[[geode-caching-provider-inline-caching-asynchronous-asynceventlistener]] [[geode-caching-provider-inline-caching-asynchronous-asynceventlistener]]
====== Implementing an AsyncEventListener for Inline Caching ====== Implementing an AsyncEventListener for Inline Caching
If you were to configure asynchronous (write-behind) inline caching by hand, you would need to do all of If you were to configure asynchronous, write-behind Inline caching by hand, you would need to do the following yourself:
the following yourself:
1. Implement an `AsyncEventListener` to write to an external data source on cache events. . Implement an `AsyncEventListener` to write to an external data source on cache events.
2. Configure, create, and register the listener with an `AsyncEventQueue` (AEQ). . Configure and register the listener with an `AsyncEventQueue` (AEQ).
3. Create a region to serve as the source of cache events and attach the AEQ to the region. . Create a Region to serve as the source of cache events and attach the AEQ to the Region.
The advantage of this approach is that you have access to and control over low-level configuration details. The disadvantage The advantage of this approach is that you have access to and control over low-level configuration details.
is that with more moving parts, it is easier to make errors. The disadvantage is that with more moving parts, it is easier to make errors.
Following on from our synchronous (read/write-through_) inline caching examples from the prior sections, Following on from our synchronous, read/write-through, Inline caching examples from the prior sections,
our `AsyncEventListener` implementation might appear as follows: our `AsyncEventListener` implementation might appear as follows:
.Example `AsyncEventListener` for Async _Inline Caching_ .Example `AsyncEventListener` for Asynchronous, Write-Behind Inline Caching
==== ====
[source,java] [source,java]
---- ----
@@ -562,7 +559,7 @@ class ExampleAsyncEventListener implements AsyncEventListener {
@Override @Override
public boolean processEvents(List<AsyncEvent> events) { public boolean processEvents(List<AsyncEvent> events) {
// Iterate over the ordered AsyncEvents and use the DataSource // Iterate over the ordered AsyncEvents and use the configured DataSource
// to write to the external, backend DataSource // to write to the external, backend DataSource
} }
@@ -570,14 +567,14 @@ class ExampleAsyncEventListener implements AsyncEventListener {
---- ----
==== ====
NOTE: Instead of directly injecting a `DataSource` into your `AsyncEventListener`, you could use JDBC, NOTE: Instead of directly injecting a `DataSource` into your `AsyncEventListener`, you could use JDBC, Spring's
Spring's `JdbcTemplate`, JPA and Hibernate, or another data access API or framework. Later in this chapter, we show how SBDG `JdbcTemplate`, JPA and Hibernate, or another data access API or framework. Later in this chapter, we show how SBDG
simplifies the `AsyncEventListener` implementation by using Spring Data repositories. simplifies the `AsyncEventListener` implementation by using Spring Data Repositories.
Then we need to register this listener with a `AsyncEventQueue` (AEQ) (step 2 from the algorithm shown earlier) and attach it to the target region Then we need to register this listener with an `AsyncEventQueue` (step 2 from the procedure shown earlier) and attach it
that will be the source of the cache events we want to persist asynchronously (step 3): to the target Region that will be the source of the cache events we want to persist asynchronously (step 3):
.Configure and Create an `AsyncEventQueue` .Create and Configure an `AsyncEventQueue`
==== ====
[source,java] [source,java]
---- ----
@@ -587,7 +584,7 @@ class GeodeConfiguration {
@Bean @Bean
DataSource exampleDataSource() { DataSource exampleDataSource() {
// Configure and construct a data store specific DataSource // Construct and configure a data store specific DataSource
} }
@Bean @Bean
@@ -627,7 +624,7 @@ class GeodeConfiguration {
While this approach affords you a lot of control over the low-level configuration, in addition to While this approach affords you a lot of control over the low-level configuration, in addition to
your `AsyncEventListener` implementation, this is a lot of boilerplate code. your `AsyncEventListener` implementation, this is a lot of boilerplate code.
TIP: See the Javadoc on SDG's {spring-data-geode-javadoc}/org/springframework/data/gemfire/wan/AsyncEventQueueFactoryBean.html[`AsyncEventQueueFactoryBean`] TIP: See the Javadoc for SDG's {spring-data-geode-javadoc}/org/springframework/data/gemfire/wan/AsyncEventQueueFactoryBean.html[`AsyncEventQueueFactoryBean`]
for more detail on the configuration of the AEQ. for more detail on the configuration of the AEQ.
TIP: See {geode-name}'s {apache-geode-docs}/developing/events/implementing_write_behind_event_handler.html[User Guide] TIP: See {geode-name}'s {apache-geode-docs}/developing/events/implementing_write_behind_event_handler.html[User Guide]
@@ -638,10 +635,11 @@ Fortunately, with SBDG, there is a better way.
[[geode-caching-provider-inline-caching-asynchronous-using-spring-data-repositories]] [[geode-caching-provider-inline-caching-asynchronous-using-spring-data-repositories]]
====== Asynchronous Inline Caching with Spring Data Repositories ====== Asynchronous Inline Caching with Spring Data Repositories
The implementation and configuration of the `AsyncEventListener` as well as the AEQ shown in the <<geode-caching-provider-inline-caching-asynchronous-asynceventlistener,preceding section>> can be simplified The implementation and configuration of the `AsyncEventListener` as well as the AEQ shown in
as follows: the <<geode-caching-provider-inline-caching-asynchronous-asynceventlistener,preceding section>>
can be simplified as follows:
.Using SBDG to configure Asynchronous (Write-Behind) Inline Caching .Using SBDG to configure Asynchronous, Write-Behind Inline Caching
==== ====
[source,java] [source,java]
---- ----
@@ -666,8 +664,8 @@ class ExampleSpringBootApacheGeodeAsyncInlineCachingApplication {
==== ====
The `AsyncInlineCachingRegionConfigurer.create(..)` method is overloaded to accept a `Predicate` in place of the `String` The `AsyncInlineCachingRegionConfigurer.create(..)` method is overloaded to accept a `Predicate` in place of the `String`
to programmatically express more powerful matching logic and identify the target region (by name) on which to to programmatically express more powerful matching logic and identify the target Region (by name) on which to configure
configure asynchronous inline caching functionality. asynchronous Inline caching functionality.
The `AsyncInlineCachingRegionConfigurer` uses the https://en.wikipedia.org/wiki/Builder_pattern[Builder software design pattern] The `AsyncInlineCachingRegionConfigurer` uses the https://en.wikipedia.org/wiki/Builder_pattern[Builder software design pattern]
and `withQueue*(..)` builder methods to configure the underlying `AsyncEventQueue` (AEQ) when the queue's configuration and `withQueue*(..)` builder methods to configure the underlying `AsyncEventQueue` (AEQ) when the queue's configuration
@@ -682,22 +680,21 @@ With the power of Spring Boot auto-configuration and SBDG, the configuration is
[[geode-caching-provider-inline-caching-asynchronous-listener]] [[geode-caching-provider-inline-caching-asynchronous-listener]]
====== About `RepositoryAsyncEventListener` ====== About `RepositoryAsyncEventListener`
The SBDG `RepositoryAsyncEventListener` class is the magic sauce behind the integration of the cache with an external The SBDG `RepositoryAsyncEventListener` class is the magic ingredient behind the integration of the cache with
data source. an external data source.
The listener is a specialized https://en.wikipedia.org/wiki/Adapter_pattern[adapter] that processes `AsyncEvents` by The listener is a specialized https://en.wikipedia.org/wiki/Adapter_pattern[adapter] that processes `AsyncEvents` by
invoking an appropriate `CrudRepository` method based on the cache operation. The listener requires an instance of invoking an appropriate `CrudRepository` method based on the cache operation. The listener requires an instance of
`CrudRepository`. The listener supports any external data source supported by Spring Data's `CrudRepository`. The listener supports any external data source supported by Spring Data's Repository abstraction.
repository abstraction.
Backend data-store, data-access operations (such as INSERT, UPDATE, DELETE, and so on) triggered by cache events Backend data store, data access operations (such as INSERT, UPDATE, DELETE, and so on) triggered by cache events
are performed asynchronously from the cache operation. This means the state of the cache and backend data store are performed asynchronously from the cache operation. This means the state of the cache and backend data store
will be "`eventually consistent`". will be "eventually consistent".
Given the complex nature of "`eventually consistent`" systems and asynchronous concurrent processing, the Given the complex nature of "eventually consistent" systems and asynchronous concurrent processing, the
`RepositoryAsyncEventListener` lets you register a custom `AsyncEventErrorHandler` to handle the errors `RepositoryAsyncEventListener` lets you register a custom `AsyncEventErrorHandler` to handle the errors that occur
that occur during processing of `AsyncEvents`, perhaps due to a faulty backend data-store data-access operation during processing of `AsyncEvents`, perhaps due to a faulty backend data store data access operation (such as
(such as `OptimisticLockingFailureException`), in an application-relevant way. `OptimisticLockingFailureException`), in an application-relevant way.
The `AsyncEventErrorHandler` interface is a `java.util.function.Function` implementation and `@FunctionalInterface` The `AsyncEventErrorHandler` interface is a `java.util.function.Function` implementation and `@FunctionalInterface`
defined as: defined as:
@@ -712,11 +709,11 @@ interface AsyncEventErrorHandler implements Function<AsyncEventError, Boolean> {
==== ====
The `AsyncEventError` class encapsulates `AsyncEvent` along with the `Throwable` that was thrown while processing The `AsyncEventError` class encapsulates `AsyncEvent` along with the `Throwable` that was thrown while processing
the event. the `AsyncEvent`.
Since the `AsyncEventErrorHandler` interface implements `Function`, you should override the `apply(:AsyncEventError)` Since the `AsyncEventErrorHandler` interface implements `Function`, you should override the `apply(:AsyncEventError)`
method to handle the error with application-specific actions. The handler returns a `Boolean` to indicate whether it was method to handle the error with application-specific actions. The handler returns a `Boolean` to indicate whether it
able to handle the error or not: was able to handle the error or not:
.Custom `AsyncEventErrorHandler` implementation .Custom `AsyncEventErrorHandler` implementation
==== ====
@@ -729,11 +726,14 @@ class CustomAsyncEventErrorHandler implements AsyncEventErrorHandler {
if (error.getCause() instanceof OptimisticLockingFailureException) { if (error.getCause() instanceof OptimisticLockingFailureException) {
// handle optimistic locking failure if you can // handle optimistic locking failure if you can
return true; // if error was successfully handled. return true; // if error was successfully handled
} }
else if (error.getCause() instanceof IncorrectResultSizeDataAccessException) { else if (error.getCause() instanceof IncorrectResultSizeDataAccessException) {
// handle no row or too many row update if you can // handle no row or too many row update if you can
return true; // if error was successfully handled. return true; // if error was successfully handled
}
else {
// ...
} }
return false; return false;
@@ -760,8 +760,7 @@ class GeodeConfiguration {
@Bean @Bean
AsyncInlineCachingRegionConfigurer asyncInlineCachingRegionConfigurer( AsyncInlineCachingRegionConfigurer asyncInlineCachingRegionConfigurer(
CrudRepository<?, ?> repository, CrudRepository<?, ?> repository,
CustomAsyncEventErrorHandler errorHandler CustomAsyncEventErrorHandler errorHandler) {
) {
return AsyncInlineCachingRegionConfigurer.create(repository, "Example") return AsyncInlineCachingRegionConfigurer.create(repository, "Example")
.withAsyncEventErrorHandler(errorHandler); .withAsyncEventErrorHandler(errorHandler);
@@ -770,15 +769,15 @@ class GeodeConfiguration {
---- ----
==== ====
Also, since `AsyncEventErrorHandler` implements `Function`, you can https://en.wikipedia.org/wiki/Composite_pattern["`compose`"] Also, since `AsyncEventErrorHandler` implements `Function`, you can https://en.wikipedia.org/wiki/Composite_pattern[compose]
multiple error handlers by using {jdk-javadoc}/java/util/function/Function.html#andThen-java.util.function.Function-[`Function.andThen(:Function)`]. multiple error handlers by using {jdk-javadoc}/java/util/function/Function.html#andThen-java.util.function.Function-[`Function.andThen(:Function)`].
By default, the `RepositoryAsyncEventListener` handles `CREATE`, `UPDATE`, and `REMOVE` cache event, entry operations. By default, the `RepositoryAsyncEventListener` handles `CREATE`, `UPDATE`, and `REMOVE` cache event, entry operations.
`CREATE` and `UPDATE` translate to `CrudRepository.save(entity)`, where the `entity` is derived from `CREATE` and `UPDATE` translate to `CrudRepository.save(entity)`. The `entity` is derived from
`AsyncEvent.getDeserializedValue()`. `AsyncEvent.getDeserializedValue()`.
`REMOVE` translates to `CrudRepository.delete(entity)`, where the `entity` is derived from `REMOVE` translates to `CrudRepository.delete(entity)`. The `entity` is derived from
`AsyncEvent.getDeserializedValue()`. `AsyncEvent.getDeserializedValue()`.
The cache {apache-geode-javadoc}/org/apache/geode/cache/Operation.html[`Operation`] to `CrudRepository` method is The cache {apache-geode-javadoc}/org/apache/geode/cache/Operation.html[`Operation`] to `CrudRepository` method is
@@ -805,16 +804,17 @@ interface AsyncEventOperationRepositoryFunction<T, ID> implements Function<Async
==== ====
`T` is the class type of the entity and `ID` is the class type of the entity's identifier (ID), possibly declared with `T` is the class type of the entity and `ID` is the class type of the entity's identifier (ID), possibly declared with
Spring Data's {spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`org.springframework.data.annotation.Id`] annotation. Spring Data's {spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`org.springframework.data.annotation.Id`]
annotation.
For convenience, SBDG provides the `AbstractAsyncEventOperationRepositoryFunction` class for extension, where you can For convenience, SBDG provides the `AbstractAsyncEventOperationRepositoryFunction` class for extension, where you can
provide implementations for the `cacheProcess(:AsyncEvent)` and `doRepositoryOp(entity)` methods. provide implementations for the `cacheProcess(:AsyncEvent)` and `doRepositoryOp(entity)` methods.
NOTE: The `AsyncEventOperationRepositoryFunction.apply(:AsyncEvent)` method is already implemented in terms of NOTE: The `AsyncEventOperationRepositoryFunction.apply(:AsyncEvent)` method is already implemented in terms of
`canProcess(:AsyncEvent)`, `resolveEntity(:AsyncEvent)`, `doRepositoryOp(entity)`, and catching and handling any `canProcess(:AsyncEvent)`, `resolveEntity(:AsyncEvent)`, `doRepositoryOp(entity)`, and catching and handling
`Throwable` (errors) by calling the configured `AsyncEventErrorHandler`. any `Throwable` (errors) by calling the configured `AsyncEventErrorHandler`.
For example, you might want to handle {apache-geode-javadoc}/org/apache/geode/cache/Operation.html#INVALIDATE[`Operation.INVALIDATE`] For example, you may want to handle {apache-geode-javadoc}/org/apache/geode/cache/Operation.html#INVALIDATE[`Operation.INVALIDATE`]
cache events as well, deleting the entity from the backend data store by invoking the `CrudRepository.delete(entity)` cache events as well, deleting the entity from the backend data store by invoking the `CrudRepository.delete(entity)`
method: method:
@@ -824,7 +824,7 @@ method:
---- ----
@Component @Component
class InvalidateAsyncEventRepositoryFunction class InvalidateAsyncEventRepositoryFunction
extends RepositoryAsyncEventListener.AbstractAsyncEventOperationRepositoryFunction<?, ?> { extends RepositoryAsyncEventListener.AbstractAsyncEventOperationRepositoryFunction<?, ?> {
InvalidateAsyncEventRepositoryFunction(RepositoryAsyncEventListener<?, ?> listener) { InvalidateAsyncEventRepositoryFunction(RepositoryAsyncEventListener<?, ?> listener) {
super(listener); super(listener);
@@ -845,22 +845,23 @@ class InvalidateAsyncEventRepositoryFunction
---- ----
==== ====
You can then register your user-defined, `AsyncEventOperationRepositoryFunction` You can then register your user-defined, `AsyncEventOperationRepositoryFunction` (that is,
(that is, `InvalidateAsyncEventRepositoryFunction`) with the `RepositoryAsyncEventListener` by using the `InvalidateAsyncEventRepositoryFunction`) with the `RepositoryAsyncEventListener` by using
`AsyncInlineCachingRegionConfigurer`: the `AsyncInlineCachingRegionConfigurer`:
.Configuring a user-defined `AsyncEventOperationRepositoryFunction` .Configuring a user-defined `AsyncEventOperationRepositoryFunction`
==== ====
[source,java] [source,java]
---- ----
import org.springframework.geode.cache.RepositoryAsyncEventListener;@Configuration import org.springframework.geode.cache.RepositoryAsyncEventListener;
@Configuration
class GeodeConfiguration { class GeodeConfiguration {
@Bean @Bean
AsyncInlineCachingRegionConfigurer asyncInlineCachingRegionConfigurer( AsyncInlineCachingRegionConfigurer asyncInlineCachingRegionConfigurer(
CrudRepository<?, ?> repository, CrudRepository<?, ?> repository,
CustomerAsyncEventErrorHandler errorHandler CustomAsyncEventErrorHandler errorHandler ) {
) {
return AsyncInlineCachingRegionConfigurer.create(repository, "ExampleRegion") return AsyncInlineCachingRegionConfigurer.create(repository, "ExampleRegion")
.applyToListener(listener -> { .applyToListener(listener -> {
@@ -886,44 +887,44 @@ the default behavior for these cache operations handled by SBDG.
[[geode-caching-provider-inline-caching-asynchronous-region-configurer]] [[geode-caching-provider-inline-caching-asynchronous-region-configurer]]
====== About `AsyncInlineCachingRegionConfigurer` ====== About `AsyncInlineCachingRegionConfigurer`
As we saw in the previous section, you can intercept and post-process the key components that are constructed As we saw in the previous section, you can intercept and post-process the essential components that are constructed
and configured by the `AsyncInlineCachingRegionConfigurer` class during initialization. and configured by the `AsyncInlineCachingRegionConfigurer` class during initialization.
SBDG's lets you intercept and post-process the `AsyncEventListener` (such as `RepositoryAsyncEventListener`), the SBDG's lets you intercept and post-process the `AsyncEventListener` (such as `RepositoryAsyncEventListener`),
`AsyncEventQueueFactory` and even the `AsyncEventQueue` created by the `AsyncInlineCachingRegionConfigurer` the `AsyncEventQueueFactory` and even the `AsyncEventQueue` created by the `AsyncInlineCachingRegionConfigurer`
(a SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/RegionConfigurer.html[`RegionConfigurer`]) (a SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/RegionConfigurer.html[`RegionConfigurer`])
during Spring `ApplicationContext` bean initialization. during Spring `ApplicationContext` bean initialization.
The `AsyncInlineCachingRegionConfigurer` class provides the following builder methods to intercept and post-process The `AsyncInlineCachingRegionConfigurer` class provides the following builder methods to intercept and post-process any
any of the following {geode-name} objects: of the following {geode-name} objects:
* `applyToListener(:Function<AsyncEventListener, AsyncEventListener>)` * `applyToListener(:Function<AsyncEventListener, AsyncEventListener>)`
* `applyToQueue(:Function<AsyncEventQueue, AsyncEventQueue>)` * `applyToQueue(:Function<AsyncEventQueue, AsyncEventQueue>)`
* `applyToQueueFactory(:Function<AsyncEventQueueFactory, AsyncEventQueueFactory>)` * `applyToQueueFactory(:Function<AsyncEventQueueFactory, AsyncEventQueueFactory>)`
All of these `apply*` methods accept a `java.util.function.Function` that "`applies`" the logic of the `Function` to All of these `apply*` methods accept a `java.util.function.Function` that applies the logic of the `Function` to
the {geode-name} object (such as `AsyncEventListener`), returning the object as a result. the {geode-name} object (such as `AsyncEventListener`), returning the object as a result.
TIP: The {geode-name} object returned by the `Function` may be the same object, a proxy, or a completely new object. TIP: The {geode-name} object returned by the `Function` may be the same object, a proxy, or a completely new object.
Essentially, the returned object can be anything you want. This is the fundamental premise behind Essentially, the returned object can be anything you want. This is the fundamental premise behind Aspect-Oriented
Aspect-Oriented Programming (AOP) and the https://en.wikipedia.org/wiki/Decorator_pattern[decorator software design pattern]. Programming (AOP) and the https://en.wikipedia.org/wiki/Decorator_pattern[Decorator software design pattern].
These `apply*` methods and the supplied `Function` let you decorate, enhance, post-process, or otherwise modify The `apply*` methods and the supplied `Function` let you decorate, enhance, post-process, or otherwise modify
the {geode-name} objects created by the listener. the {geode-name} objects created by the configurer.
The `AsyncInlineCachingRegionConfigurer` strictly adheres to the https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle[open/close principle] The `AsyncInlineCachingRegionConfigurer` strictly adheres to the https://en.wikipedia.org/wiki/Open%E2%80%93closed_principle[open/close principle]
as well and is, therefore, flexibly extensible. and is, therefore, flexibly extensible.
[[geode-caching-provider-multi-site-caching]] [[geode-caching-provider-multi-site-caching]]
==== Multi-Site Caching ==== Multi-Site Caching
The final pattern of caching presented in this chapter is multi-site caching. The final pattern of caching presented in this chapter is Multi-site caching.
As described earlier, there are two configuration arrangements, depending on your application usage patterns, requirements, As described earlier, there are two configuration arrangements, depending on your application usage patterns,
and user demographic: active-active and active-passive. requirements and user demographic: active-active and active-passive.
Multi-site caching, along with active-active and active-passive configuration arrangements, are described Multi-site caching, along with active-active and active-passive configuration arrangements, are described in more detail
in more detail in the sample link:guides/caching-multi-site.html[guide]. Also, be sure to review the Sample in the sample link:guides/caching-multi-site.html[guide]. Also, be sure to review the sample
{github-samples-url}/caching/multi-site[code]. {github-samples-url}/caching/multi-site[code].
[[geode-caching-provider-advanced-configuration]] [[geode-caching-provider-advanced-configuration]]
@@ -931,33 +932,34 @@ in more detail in the sample link:guides/caching-multi-site.html[guide]. Also, b
{geode-name} supports additional caching capabilities to manage the entries stored in the cache. {geode-name} supports additional caching capabilities to manage the entries stored in the cache.
As you can imagine, given that cache entries are stored in-memory, it becomes important to monitor and manage the As you can imagine, given that cache entries are stored in-memory, it becomes important to manage and monitor
available memory wisely. After all, by default, {geode-name} stores data in the JVM Heap. the available memory used by the cache. After all, by default, {geode-name} stores data in the JVM Heap.
You can employ several techniques to more effectively manage memory, such as using You can employ several techniques to more effectively manage memory, such as using
{apache-geode-docs}/developing/eviction/chapter_overview.html[eviction], possibly {apache-geode-docs}/developing/eviction/chapter_overview.html[eviction], possibly
{apache-geode-docs}/developing/storing_data_on_disk/chapter_overview.html[overflowing data to disk], {apache-geode-docs}/developing/storing_data_on_disk/chapter_overview.html[overflowing data to disk],
configuring both entry idle-iimeout_ (TTI) and time-to-live_ (TTL) configuring both entry Idle-Timeout_ (TTI) and Time-to-Live_ (TTL)
{apache-geode-docs}/developing/expiration/chapter_overview.html[expiration policies], {apache-geode-docs}/developing/expiration/chapter_overview.html[expiration policies],
configuring {apache-geode-docs}/managing/region_compression.html[compression], configuring {apache-geode-docs}/managing/region_compression.html[compression],
and using {apache-geode-docs}/managing/heap_use/off_heap_management.html[off-heap] or main memory. and using {apache-geode-docs}/managing/heap_use/off_heap_management.html[off-heap]
or main memory.
You can use several other strategies as well, as described in You can use several other strategies as well, as described in
{apache-geode-docs}/managing/heap_use/heap_management.html[Managing Heap and Off-heap Memory]. {apache-geode-docs}/managing/heap_use/heap_management.html[Managing Heap and Off-heap Memory].
While this is well beyond the scope of this document, know that Spring Data for {geode-name} makes all of these While this is beyond the scope of this document, know that Spring Data for {geode-name} makes all of these
{spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[configuration options] available. {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[configuration options] available to you.
[[geode-caching-provider-disable]] [[geode-caching-provider-disable]]
=== Disable Caching === Disable Caching
There may be cases where you do not want your Spring Boot application to cache application state with There may be cases where you do not want your Spring Boot application to cache application state with
{spring-framework-docs}/integration.html#cache[Spring's cache abstraction] using {geode-name}. In certain cases, you {spring-framework-docs}/integration.html#cache[Spring's Cache Abstraction] using {geode-name}. In certain cases,
may use another Spring supported caching provider, such as Redis, to cache and manage your application state. you may use another Spring supported caching provider, such as Redis, to cache and manage your application state.
In other cases, you may not want to use Spring's cache abstraction at all. In other cases, you may not want to use Spring's Cache Abstraction at all.
Either way, you can specifically call out your Spring cache abstraction provider by using the `spring.cache.type` property Either way, you can specifically call out your Spring Cache Abstraction provider by using the `spring.cache.type`
in `application.properties`: property in `application.properties`:
.Use Redis as the Spring Cache Abstraction Provider .Use Redis as the Spring Cache Abstraction Provider
==== ====
@@ -970,8 +972,8 @@ spring.cache.type=redis
---- ----
==== ====
If you prefer not to use Spring's Cache Abstraction to manage your Spring Boot application's state at all, then If you prefer not to use Spring's Cache Abstraction to manage your Spring Boot application's state at all, then set
do the following: the `spring.cache.type` property to "none":
.Disable Spring's Cache Abstraction .Disable Spring's Cache Abstraction
==== ====
@@ -987,9 +989,9 @@ spring.cache.type=none
See the Spring Boot {spring-boot-docs-html}/boot-features-caching.html#boot-features-caching-provider-none[documentation] See the Spring Boot {spring-boot-docs-html}/boot-features-caching.html#boot-features-caching-provider-none[documentation]
for more detail. for more detail.
TIP: You can include multiple providers on the classpath of your Spring Boot application. For instance, TIP: You can include multiple caching providers on the classpath of your Spring Boot application. For instance,
you might use Redis to cache your application's state while using {geode-name} as your application's persistent you might use Redis to cache your application's state while using {geode-name} as your application's persistent
data store (the system of record). data store (that is, the System of Record (SOR)).
NOTE: Spring Boot does not properly recognize `spring.cache.type=[gemfire|geode]`, even though Spring Boot NOTE: Spring Boot does not properly recognize `spring.cache.type=[gemfire|geode]`, even though Spring Boot
for {geode-name} is set up to handle either of these property values (either `gemfire` or `geode`). for {geode-name} is set up to handle either of these property values (that is, either `gemfire` or `geode`).

View File

@@ -4,16 +4,16 @@
The first opinionated option provided to you by Spring Boot for {geode-name} (SBDG) is a The first opinionated option provided to you by Spring Boot for {geode-name} (SBDG) is a
{apache-geode-javadoc}/org/apache/geode/cache/client/ClientCache.html[`ClientCache`] instance that you get by declaring {apache-geode-javadoc}/org/apache/geode/cache/client/ClientCache.html[`ClientCache`] instance
Spring Boot for {geode-name} on your application classpath. that you get by declaring Spring Boot for {geode-name} on your application classpath.
It is assumed that most application developers who use Spring Boot to build applications backed by {geode-name} are It is assumed that most application developers who use Spring Boot to build applications backed by {geode-name}
building cache client applications deployed in an {geode-name} are building cache client applications deployed in an {geode-name}
{apache-geode-docs}/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology]. {apache-geode-docs}/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology].
The client/server topology is the most common and traditional architecture employed by enterprise applications that The client/server topology is the most common and traditional architecture employed by enterprise applications
use {geode-name}. that use {geode-name}.
For example, you can begin building a Spring Boot, {geode-name} `ClientCache` application by declaring the For example, you can begin building a Spring Boot {geode-name} `ClientCache` application by declaring the
`spring-geode-starter` on your application's classpath: `spring-geode-starter` on your application's classpath:
.Spring Boot for {geode-name} on the application classpath .Spring Boot for {geode-name} on the application classpath
@@ -44,12 +44,12 @@ public class SpringBootApacheGeodeClientCacheApplication {
---- ----
==== ====
Your application now has a `ClientCache` instance that can connect to an {geode-name} server running on Your application now has a `ClientCache` instance that can connect to an {geode-name} server running on `localhost`
`localhost` and listen on the default `CacheServer` port, `40404`. and listening on the default `CacheServer` port, `40404`.
By default, an {geode-name} server (that is, `CacheServer`) must be running for the application to use the `ClientCache` instance. By default, an {geode-name} server (that is, `CacheServer`) must be running for the application to use the `ClientCache`
However, it is perfectly valid to create a `ClientCache` instance and perform data access operations by using `LOCAL` instance. However, it is perfectly valid to create a `ClientCache` instance and perform data access operations by using
Regions. This is useful during development. `LOCAL` Regions. This is useful during development.
TIP: To develop with `LOCAL` Regions, configure your cache Regions with the TIP: To develop with `LOCAL` Regions, configure your cache Regions with the
{apache-geode-javadoc}/org/apache/geode/cache/client/ClientRegionShortcut.html#LOCAL[`ClientRegionShortcut.LOCAL`] {apache-geode-javadoc}/org/apache/geode/cache/client/ClientRegionShortcut.html#LOCAL[`ClientRegionShortcut.LOCAL`]
@@ -63,9 +63,9 @@ TIP: Compare and contrast the preceding configuration with the Spring Data for {
{spring-data-geode-docs-html}/#bootstrap-annotation-config-geode-applications[approach]. {spring-data-geode-docs-html}/#bootstrap-annotation-config-geode-applications[approach].
It is uncommon to ever need a direct reference to the `ClientCache` instance provided by SBDG injected into your It is uncommon to ever need a direct reference to the `ClientCache` instance provided by SBDG injected into your
application components (for example, `@Service` or `@Repository` beans defined in a Spring `ApplicationContext`), whether you application components (for example, `@Service` or `@Repository` beans defined in a Spring `ApplicationContext`),
are configuring additional {geode-name} objects (regions, indexes, and so on) or are using those objects indirectly whether you are configuring additional {geode-name} objects (Regions, Indexes, and so on) or are using those objects
in your applications. However, it is possible to do so if and when needed. indirectly in your applications. However, it is possible to do so if and when needed.
For example, perhaps you want to perform some additional `ClientCache` initialization in a Spring Boot For example, perhaps you want to perform some additional `ClientCache` initialization in a Spring Boot
{spring-boot-javadoc}/org/springframework/boot/ApplicationRunner.html[`ApplicationRunner`] on startup: {spring-boot-javadoc}/org/springframework/boot/ApplicationRunner.html[`ApplicationRunner`] on startup:
@@ -101,18 +101,19 @@ public class SpringBootApacheGeodeClientCacheApplication {
What if you want to build an embedded peer `Cache` application instead? What if you want to build an embedded peer `Cache` application instead?
Perhaps you need an actual peer cache member, configured and bootstrapped with Spring Boot, along with the ability Perhaps you need an actual peer cache member, configured and bootstrapped with Spring Boot, along with the ability
to join this member to an existing cluster (of data servers) as a peer node. You can do that too. to join this member to an existing cluster (of data servers) as a peer node.
Remember the second goal in Spring Boot's {spring-boot-docs-html}/#getting-started-introducing-spring-boot[documentation]: Remember the second goal in Spring Boot's {spring-boot-docs-html}/#getting-started-introducing-spring-boot[documentation]:
> Be opinionated out of the box but get out of the way quickly as requirements start to diverge from the defaults. > Be opinionated out of the box but get out of the way quickly as requirements start to diverge from the defaults.
Here, we focus on the second part of the goal: "`get out of the way quickly as requirements start to diverge from the defaults`" Here, we focus on the second part of the goal: "_get out of the way quickly as requirements start to diverge
from the defaults_".
If your application requirements demand you use Spring Boot to configure and bootstrap an embedded peer `Cache` If your application requirements demand you use Spring Boot to configure and bootstrap an embedded peer `Cache` instance,
instance, declare your intention with either SDG's declare your intention with either SDG's
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html[`@PeerCacheApplication`] annotation, {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html[`@PeerCacheApplication`] annotation,
or, if you also need to enable connections from `ClientCache` apps, use SDG's or, if you also need to enable connections from `ClientCache` applications, use SDG's
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/CacheServerApplication.html[`@CacheServerApplication`] annotation: {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/CacheServerApplication.html[`@CacheServerApplication`] annotation:
.Spring Boot, {geode-name} `CacheServer` Application .Spring Boot, {geode-name} `CacheServer` Application
@@ -130,21 +131,19 @@ public class SpringBootApacheGeodeCacheServerApplication {
---- ----
==== ====
TIP: An {geode-name} "`server`" is not necessarily a `CacheServer` capable of serving cache clients. It is merely a peer TIP: An {geode-name} server is not necessarily a `CacheServer` capable of serving cache clients. It is merely a peer
member node in an {geode-name} cluster (that is, a distributed system) that stores and manages data. member node in an {geode-name} cluster (that is, a distributed system) that stores and manages data.
By explicitly declaring the `@CacheServerApplication` annotation, you tell Spring Boot that you do not want By explicitly declaring the `@CacheServerApplication` annotation, you tell Spring Boot that you do not want the default
the default `ClientCache` instance but rather want an embedded peer `Cache` instance with a `CacheServer` component, `ClientCache` instance but rather want an embedded peer `Cache` instance with a `CacheServer` component, which enables
which enables connections from `ClientCache` apps. connections from `ClientCache` applications.
You can also enable two other {geode-name} services: You can also enable two other {geode-name} services:
* An embedded _Locator_, which allows clients or even other peers * An embedded _Locator_, which allows clients or even other peers to locate servers in the cluster.
to "`locate`" servers in the cluster. * An embedded _Manager_, which allows the {geode-name} application process to be managed and monitored by using
* An embedded _Manager_, which allows the {geode-name} application process {apache-geode-docs}/tools_modules/gfsh/chapter_overview.html[Gfsh], {geode-name}'s command-line shell tool:
to be managed and monitored by using {apache-geode-docs}/tools_modules/gfsh/chapter_overview.html[Gfsh], {geode-name}'s
command-line shell:
.Spring Boot, {geode-name} `CacheServer` Application with _Locator_ and _Manager_ services enabled .Spring Boot {geode-name} `CacheServer` Application with _Locator_ and _Manager_ services enabled
==== ====
[source,java] [source,java]
---- ----
@@ -161,7 +160,7 @@ public class SpringBootApacheGeodeCacheServerApplication {
---- ----
==== ====
Then you can use Gfsh to connect to and manage this server: Then you can use Gfsh to connect to and manage this server:
==== ====
[source,text] [source,text]
@@ -189,7 +188,7 @@ gfsh>list members
------------------------------------------- | -------------------------------------------------------------------------- ------------------------------------------- | --------------------------------------------------------------------------
SpringBootApacheGeodeCacheServerApplication | 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:29798)<ec><v0>:1024 SpringBootApacheGeodeCacheServerApplication | 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:29798)<ec><v0>:1024
gfsh>
gfsh>describe member --name=SpringBootApacheGeodeCacheServerApplication gfsh>describe member --name=SpringBootApacheGeodeCacheServerApplication
Name : SpringBootApacheGeodeCacheServerApplication Name : SpringBootApacheGeodeCacheServerApplication
Id : 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:29798)<ec><v0>:1024 Id : 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:29798)<ec><v0>:1024
@@ -211,10 +210,10 @@ Client Connections : 0
---- ----
==== ====
You can even start additional servers in Gfsh. These additional servers connect to your configured and bootstrapped Spring Boot, You can even start additional servers in Gfsh. These additional servers connect to your Spring Boot configured
{geode-name} `CacheServer` application. These additional servers started in Gfsh know about the Spring Boot, and bootstrapped {geode-name} `CacheServer` application. These additional servers started in Gfsh know about
{geode-name} server because of the embedded lcator service, which is running on `localhost` and listening on the Spring Boot, {geode-name} server because of the embedded Locator service, which is running on `localhost`
the default locator port, `10334`: and listening on the default Locator port, `10334`:
==== ====
[source,text] [source,text]
@@ -240,9 +239,9 @@ GfshServer | 10.0.0.121(GfshServer:30031)<v1>:1
---- ----
==== ====
Perhaps you want to start the other way around. You may need to connect a configured Perhaps you want to start the other way around. You may need to connect a Spring Boot configured and bootstrapped
and bootstrapped Spring Boot, {geode-name} server application to an existing cluster. You can start the cluster in Gfsh {geode-name} server application to an existing cluster. You can start the cluster in Gfsh with the following commands
with the following commands (shown with partial typical output): (shown with partial typical output):
==== ====
[source,text] [source,text]
@@ -287,7 +286,7 @@ GfshServer | 10.0.0.121(GfshServer:30270)<v1>:1025
Then modify the `SpringBootApacheGeodeCacheServerApplication` class to connect to the existing cluster: Then modify the `SpringBootApacheGeodeCacheServerApplication` class to connect to the existing cluster:
.Spring Boot, {geode-name} `CacheServer` Application connecting to an external cluster .Spring Boot {geode-name} `CacheServer` Application connecting to an external cluster
==== ====
[source,java] [source,java]
---- ----
@@ -303,10 +302,11 @@ public class SpringBootApacheGeodeCacheServerApplication {
==== ====
TIP: Notice that the `SpringBootApacheGeodeCacheServerApplication` class, `@CacheServerApplication` annotation's TIP: Notice that the `SpringBootApacheGeodeCacheServerApplication` class, `@CacheServerApplication` annotation's
`locators` property are configured with the host and port (`localhost[11235]`), on which the locator was started by using _Gfsh_. `locators` property are configured with the host and port (`localhost[11235]`), on which the Locator was started
by using Gfsh.
After running your Spring Boot, {geode-name} `CacheServer` application again and then running `list members` in Gfsh, After running your Spring Boot {geode-name} `CacheServer` application again and executing the `list members` command
you should see output similar to the following when you run the `list members` command: in Gfsh again, you should see output similar to the following:
==== ====
[source,text] [source,text]
@@ -340,20 +340,20 @@ Client Connections : 0
---- ----
==== ====
In both scenarios, the configured and bootstrapped Spring Boot, {geode-name} server and the Gfsh locator In both scenarios, the Spring Boot configured and bootstrapped {geode-name} server, the Gfsh Locator and Gfsh server
and Gfsh server formed a cluster. formed a cluster.
While you can use either approach and Spring does not care, it is far more convenient to use Spring Boot and your IDE While you can use either approach and Spring does not care, it is far more convenient to use Spring Boot and your IDE
to form a small cluster while developing. Spring profiles make it far simpler and much faster to to form a small cluster while developing. Spring profiles make it far simpler and much faster to configure and start
configure and start a small cluster. a small cluster.
Also, approach enables rapidly prototyping, testing, and debugging of your entire end-to-end application Also, this approach enables rapidly prototyping, testing, and debugging your entire end-to-end application
and system architecture, all right from the comfort and familiarity of your IDE. No additional tooling and system architecture right from the comfort and familiarity of your IDE. No additional tooling (such as Gfsh)
(such as Gfsh) or knowledge is required to get started quickly and easily. Just build and run. or knowledge is required to get started quickly and easily. Just build and run.
TIP: Be careful to vary your port numbers for the embedded services, like the `CacheServer`, locators, and the manager, TIP: Be careful to vary your port numbers for the embedded services, like the `CacheServer`, Locators, and the Manager,
especially if you start multiple instances. Otherwise, you are likely to run into a `java.net.BindException` especially if you start multiple instances on the same machine. Otherwise, you are likely to run into
due to port conflicts. a `java.net.BindException` caused by port conflicts.
TIP: See the <<geode-cluster-configuration-bootstrapping>> appendix for more details. TIP: See the <<geode-cluster-configuration-bootstrapping>> appendix for more details.
@@ -361,23 +361,23 @@ TIP: See the <<geode-cluster-configuration-bootstrapping>> appendix for more det
=== Building Locator Applications === Building Locator Applications
In addition to `ClientCache`, `CacheServer`, and peer `Cache` applications, SDG, and by extension SBDG, now supports In addition to `ClientCache`, `CacheServer`, and peer `Cache` applications, SDG, and by extension SBDG, now supports
locator-based Spring Boot applications. Spring Boot {geode-name} Locator applications.
An {geode-name} locator is a location-based service or, more typically, a standalone process that lets An {geode-name} Locator is a location-based service or, more typically, a standalone process that lets clients locate
clients locate a cluster of {geode-name} servers to manage data. Many cache clients can connect to the same cluster a cluster of {geode-name} servers to manage data. Many cache clients can connect to the same cluster to share data.
to share data. Running multiple clients is common in a Microservices architecture where you need to scale-up Running multiple clients is common in a Microservices architecture where you need to scale-up the number of application
the number of application instances to satisfy the demand. instances to satisfy the demand.
A locator is also used by joining members of an existing cluster to scale-out and increase capacity of the logically An {geode-name} Locator is also used by joining members of an existing cluster to scale-out and increase capacity of
pooled system resources (memory, CPU, and disk). A locator maintains metadata that is sent to the clients to the logically pooled system resources (memory, CPU, network and disk). A Locator maintains metadata that is sent to
enable such capabilities as single-hop data access, routing data access operations to the data node in the cluster the clients to enable such capabilities as single-hop data access to route data access operations to the data node
maintaining the data of interests. A locator also maintains load information for servers in the cluster, which enables in the cluster maintaining the data of interests. A Locator also maintains load information for servers in the cluster,
the load to be uniformly distributed across the cluster while also providing fail-over services to a redundant member which enables the load to be uniformly distributed across the cluster while also providing fail-over services to a
if the primary fails. A locator provides many more benefits, and we encourage you to read redundant member if the primary fails. A Locator provides many more benefits, and we encourage you to read the
the {apache-geode-docs}/configuring/running/running_the_locator.html[documentation] for more details. {apache-geode-docs}/configuring/running/running_the_locator.html[documentation] for more details.
As shown earlier, you can embed a locator service within either a peer `Cache` or a `CacheServer` Spring Boot application As shown earlier, you can embed a Locator service within either a Spring Boot peer `Cache` or a `CacheServer`
by using the SDG `@EnableLocator` annotation: application by using the SDG `@EnableLocator` annotation:
.Embedded Locator Service .Embedded Locator Service
==== ====
@@ -392,20 +392,19 @@ class SpringBootCacheServerWithEmbeddedLocatorApplication {
---- ----
==== ====
However, it is more common to start standalone locator JVM processes. This is useful when you want to increase However, it is more common to start standalone Locator JVM processes. This is useful when you want to increase the
the resiliency of your cluster in the face of network and process failures, which are bound to happen. If a locator JVM resiliency of your cluster in the face of network and process failures, which are bound to happen. If a Locator JVM
process crashes or gets severed from the cluster due to a network failure, having multiple Locators provides a process crashes or gets severed from the cluster due to a network failure or partition, having multiple Locators
higher degree of availability (HA) through redundancy. provides a higher degree of availability (HA) through redundancy.
However, if all Locators in the cluster go down, the cluster still remains intact. Even if all Locators in the cluster go down, the cluster still remains intact. You cannot add more peer members
You cannot add more peer members (that is, scale-up the number of data nodes in the cluster) (that is, scale-up the number of data nodes in the cluster) or connect any more clients, but the cluster is fine.
or connect any more clients. If all the locators in the cluster go down, it is safe to restart them If all the locators in the cluster go down, it is safe to restart them only after a thorough diagnosis.
only after a thorough diagnosis.
NOTE: Once a client receives metadata about the cluster of servers, all data-access operations are sent directly NOTE: Once a client receives metadata about the cluster of servers, all data-access operations are sent directly to
to servers in the cluster, not a locator. Therefore, existing, connected clients remain connected and operable. servers in the cluster, not a Locator. Therefore, existing, connected clients remain connected and operable.
To configure and bootstrap locator-based Spring Boot applications as standalone JVM processes, use the following To configure and bootstrap Spring Boot {geode-name} Locator applications as standalone JVM processes, use the following
configuration: configuration:
.Standalone Locator Process .Standalone Locator Process
@@ -425,16 +424,15 @@ Instead of using the `@EnableLocator` annotation, you now use the `@LocatorAppli
The `@LocatorApplication` annotation works in the same way as the `@PeerCacheApplication` and `@CacheServerApplication` The `@LocatorApplication` annotation works in the same way as the `@PeerCacheApplication` and `@CacheServerApplication`
annotations, bootstrapping an {geode-name} process and overriding the default `ClientCache` instance provided by SBDG. annotations, bootstrapping an {geode-name} process and overriding the default `ClientCache` instance provided by SBDG.
NOTE: If your `@SpringBootApplication` class is annotated with `@LocatorApplication`, it must be a `Locator` NOTE: If your `@SpringBootApplication` class is annotated with `@LocatorApplication`, it must be a `Locator` and not
and not a `ClientCache`, `CacheServer`, or peer `Cache` application. If you need the application to function as a a `ClientCache`, `CacheServer`, or peer `Cache` application. If you need the application to function as a peer `Cache`,
peer `Cache`, perhaps with an embedded `CacheServer` components and embedded locator, you need to follow perhaps with embedded `CacheServer` components and an embedded Locator, you need to follow the approach shown earlier:
the approach shown earlier: using the `@EnableLocator` annotation with either the `@PeerCacheApplication` using the `@EnableLocator` annotation with either the `@PeerCacheApplication` or `@CacheServerApplication` annotation.
or `@CacheServerApplication` annotation.
With our Spring Boot, {geode-name} locator application, we can connect both configured and bootstrapped Spring Boot With our Spring Boot {geode-name} Locator application, we can connect both Spring Boot configured and bootstrapped
peer members (peer `Cache`, `CacheServer` and `Locator` applications) as well as Gfsh started locators and servers. peer members (peer `Cache`, `CacheServer` and `Locator` applications) as well as Gfsh started Locators and servers.
First, we need to start two locators by using our {geode-name} locator Spring Boot application class. First, we need to start two Locators by using our Spring Boot {geode-name} Locator application class:
.SpringBootApacheGeodeLocatorApplication class .SpringBootApacheGeodeLocatorApplication class
==== ====
@@ -444,30 +442,31 @@ include::{docs-src-dir}/org/springframework/geode/docs/example/app/locator/Sprin
---- ----
==== ====
We also need to vary the configuration for each locator application instance. We also need to vary the configuration for each Locator application instance.
{geode-name} requires each peer member in the cluster to be uniquely named. We can set the name of the locator by using {geode-name} requires each peer member in the cluster to be uniquely named. We can set the name of the Locator by using
the `spring.data.gemfire.locator.name` SDG property set as a JVM System Property in your IDE's run configuration profile the `spring.data.gemfire.locator.name` SDG property set as a JVM System Property in your IDE's run configuration profile
for the application main class: `-Dspring.data.gemfire.locator.name=SpringLocatorOne`. We name the second for the main application class: `-Dspring.data.gemfire.locator.name=SpringLocatorOne`. We name the second Locator
locator application instance `SpringLocatorTwo`. application instance `SpringLocatorTwo`.
Additionally, we must vary the port numbers that the locators use to listen for connections. By default, an {geode-name} Additionally, we must vary the port numbers that the Locators use to listen for connections. By default, an {geode-name}
locator listens on port `10334`. We can set the locator port by using the `spring.data.gemfire.locator.port` SDG property. Locator listens on port `10334`. We can set the Locator port by using the `spring.data.gemfire.locator.port`
SDG property.
For our first locator application instance (`SpringLocatorOne`), we also enable the manager profile so that For our first Locator application instance (`SpringLocatorOne`), we also enable the "manager" profile so that
we can connect to the locator by using Gfsh. we can connect to the Locator by using Gfsh.
Our IDE run configuration profile for our first locator application instance appears as: Our IDE run configuration profile for our first Locator application instance appears as:
`-server -ea -Dspring.profiles.active=manager -Dspring.data.gemfire.locator.name=SpringLocatorOne -Dlogback.log.level=INFO` `-server -ea -Dspring.profiles.active=manager -Dspring.data.gemfire.locator.name=SpringLocatorOne -Dlogback.log.level=INFO`
And our IDE run configuration profile for our second locator application instance appears as: And our IDE run configuration profile for our second Locator application instance appears as:
`-server -ea -Dspring.profiles.active= -Dspring.data.gemfire.locator.name=SpringLocatorTwo -Dspring.data.gemfire.locator.port=11235 -Dlogback.log.level=INFO` `-server -ea -Dspring.profiles.active= -Dspring.data.gemfire.locator.name=SpringLocatorTwo -Dspring.data.gemfire.locator.port=11235 -Dlogback.log.level=INFO`
You should see log output similar to the following when you start a locator app instance: You should see log output similar to the following when you start a Locator application instance:
.Spring Boot, {geode-name} Locator log output .Spring Boot {geode-name} Locator log output
==== ====
[source,txt] [source,txt]
---- ----
@@ -547,8 +546,8 @@ Press <enter> to exit!
---- ----
==== ====
Next, start up the second locator application instance (you should see log output similar to the preceding list). Then connect to Next, start up the second Locator application instance (you should see log output similar to the preceding list).
the cluster of Locators by using Gfsh: Then connect to the cluster of Locators by using Gfsh:
.Cluster of Locators .Cluster of Locators
==== ====
@@ -580,7 +579,7 @@ SpringLocatorTwo | 10.99.199.24(SpringLocatorTwo:30077:locator)<ec><v1>:41001
==== ====
By using our `SpringBootApacheGeodeCacheServerApplication` main class from the previous section, we can configure By using our `SpringBootApacheGeodeCacheServerApplication` main class from the previous section, we can configure
and bootstrap an {geode-name} `CacheServer` application with Spring Boot and connect it to our cluster of locators: and bootstrap an {geode-name} `CacheServer` application with Spring Boot and connect it to our cluster of Locators:
.SpringBootApacheGeodeCacheServerApplication class .SpringBootApacheGeodeCacheServerApplication class
==== ====
@@ -590,7 +589,7 @@ include::{docs-src-dir}/org/springframework/geode/docs/example/app/server/Spring
---- ----
==== ====
To do so, enable the "`clustered`" profile by using an IDE run profile configuration similar to: To do so, enable the "clustered" profile by using an IDE run profile configuration similar to:
`-server -ea -Dspring.profiles.active=clustered -Dspring.data.gemfire.name=SpringServer -Dspring.data.gemfire.cache.server.port=41414 -Dlogback.log.level=INFO` `-server -ea -Dspring.profiles.active=clustered -Dspring.data.gemfire.name=SpringServer -Dspring.data.gemfire.cache.server.port=41414 -Dlogback.log.level=INFO`
@@ -609,7 +608,7 @@ SpringServer | 10.99.199.24(SpringServer:30216)<v2>:41002
---- ----
==== ====
Finally, we can even start additional Locators and Servers connected to this cluster by using Gfsh: Finally, we can even start additional Locators and servers connected to this cluster by using Gfsh:
.Gfsh started Locators and Servers .Gfsh started Locators and Servers
==== ====
@@ -656,19 +655,19 @@ for {geode-name} (SBDG) in particular, make doing so easy.
[[geode-manager-applications]] [[geode-manager-applications]]
=== Building Manager Applications === Building Manager Applications
As discussed in the previous sections, you can enable a configured and bootstrapped Spring Boot, As discussed in the previous sections, you can enable a Spring Boot configured and bootstrapped {geode-name}
{geode-name} peer member node in the cluster to function as a manager. peer member node in the cluster to function as a Manager.
An {geode-name} manager is a peer member node in the cluster that runs the management service, letting the cluster An {geode-name} Manager is a peer member node in the cluster that runs the management service, letting the cluster
be managed and monitored by using JMX-based tools, such as Gfsh, JConsole, or JVisualVM. Any tool be managed and monitored with JMX-based tools, such as Gfsh, JConsole, or JVisualVM. Any tool using the JMX API
that uses the JMX API can connect to and manage an {geode-name} cluster for whatever purpose. can connect to and manage an {geode-name} cluster for whatever purpose.
The cluster may have more than one manager, for redundancy. Only server-side, peer member nodes in the cluster Like Locators, the cluster may have more than one Manager for redundancy. Only server-side, peer member nodes
may function as managers. Therefore, a `ClientCache` application cannot be a manager. in the cluster may function Managers. Therefore, a `ClientCache` application cannot be a Manager.
To create a manager, use the SDG `@EnableManager` annotation. To create a Manager, use the SDG `@EnableManager` annotation.
The three primary uses of the `@EnableManager` annotation to create a manager are: The three primary uses of the `@EnableManager` annotation to create a Manager are:
1 - CacheServer Manager Application 1 - CacheServer Manager Application
==== ====
@@ -710,22 +709,22 @@ class LocatorManagerApplication {
==== ====
#1 creates a peer `Cache` instance with a `CacheServer` component that accepts client connections along with #1 creates a peer `Cache` instance with a `CacheServer` component that accepts client connections along with
an embedded manager that lets JMX clients connect. an embedded Manager that lets JMX clients connect.
#2 creates only a peer `Cache` instance along with an embedded manager. As a peer `Cache` with no `CacheServer` #2 creates only a peer `Cache` instance along with an embedded Manager. As a peer `Cache` with no `CacheServer`
component, clients are not able to connect to this node. It is merely a server managing data. component, clients are not able to connect to this node. It is merely a server managing data.
#3 creates a locator instance with an embedded manager. #3 creates a Locator instance with an embedded Manager.
In all configuration arrangements, the manager is configured to start immediately. In all configuration arrangements, the Manager is configured to start immediately.
TIP: See the Javadoc for the TIP: See the Javadoc for the
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html[`@EnableManager` annotation] {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html[`@EnableManager` annotation]
for additional configuration options. for additional configuration options.
As of {geode-name} 1.11.0, you must include additional {geode-name} dependencies on your Spring Boot application As of {geode-name} 1.11.0, you must include additional {geode-name} dependencies on your Spring Boot application
classpath to make your application a proper {geode-name} manager in the cluster, particularly if you also enable classpath to make your application a proper {geode-name} Manager in the cluster, particularly if you also enable
the embedded HTTP service in the manager. the embedded HTTP service in the Manager.
The required dependencies are: The required dependencies are:
@@ -750,10 +749,12 @@ and `spring-boot-starter-jetty` dependencies.
Optionally, you may also include the `geode-pulse` dependency, as follows: Optionally, you may also include the `geode-pulse` dependency, as follows:
.Additional, optional Manager depdendencies expressed in Gradle .Additional, optional Manager depdendencies expressed in Gradle
====
[source,groovy] [source,groovy]
---- ----
runtime "org.apache.geode:geode-pulse" runtime "org.apache.geode:geode-pulse"
---- ----
====
The `geode-pulse` dependency is only required if you want the _Manager_ to automatically start The `geode-pulse` dependency is only required if you want the _Manager_ to automatically start
the {geode-name} {apache-geode-docs}/tools_modules/pulse/pulse-overview.html[Pulse] Monitoring Tool. _Pulse_ enables the {geode-name} {apache-geode-docs}/tools_modules/pulse/pulse-overview.html[Pulse] Monitoring Tool. _Pulse_ enables

View File

@@ -5,36 +5,36 @@
:pcc-name: Pivotal Cloud Cache :pcc-name: Pivotal Cloud Cache
:pcf-name: Pivotal CloudFoundry :pcf-name: Pivotal CloudFoundry
NOTE: As of the VMware, Inc., acquisition of Pivotal Software, Inc., {pcf-name} (PCF) is now known as VMware Tanzu NOTE: As of the VMware, Inc. acquisition of Pivotal Software, Inc., {pcf-name} (PCF) is now known as VMware Tanzu
Application Service (TAS) for VMs. Also, {pcc-name} (PCC) has been rebranded as VMware Tanzu GemFire for VMS. Application Service (TAS) for VMs. Also, {pcc-name} (PCC) has been rebranded as VMware Tanzu GemFire for VMS.
This documentation will eventually be updated to reflect the rebranding. This documentation will eventually be updated to reflect the rebranding.
In most cases, when you deploy (that is, "`push`") your Spring Boot applications to {pcf-name} (PCF), you bind your app In most cases, when you deploy (that is, `cf push`) your Spring Boot applications to {pcf-name} (PCF), you bind
to one or more instances of the {pcc-name} (PCC) service. your application to one or more instances of the {pcc-name} (PCC) service.
In a nutshell, {pivotal-cloudcache-website}[{pcc-name}] (PCC) is a managed version of In a nutshell, {pivotal-cloudcache-website}[{pcc-name}] (PCC) is a managed version of
{pivotal-gemfire-website}[Pivotal GemFire] that runs in {pivotal-cloudfoundry-website}[{pcf-name}] (PCF). {pivotal-gemfire-website}[{pivotal-gemfire-name}] that runs in {pivotal-cloudfoundry-website}[{pcf-name}] (PCF).
When running in or across cloud environments (such as AWS, Azure, GCP, or PWS), PCC with PCF offers several advantages When running in or across cloud environments (such as AWS, Azure, GCP, or PWS), PCC with PCF offers several advantages
over trying to run and manage your own standalone {geode-name} clusters. It handles many of the infrastructure-related, over trying to run and manage your own standalone {geode-name} clusters. It handles many of the infrastructure-related,
operational concerns so that you need not do so. operational concerns so that you need not do so.
[[cloudfoundry-cloudcache-security-auth-runtime-user-configuration]] [[cloudfoundry-cloudcache-security-auth-runtime-user-configuration]]
=== Running Spring Boot applications as a specific user === Running a Spring Boot application as a specific user
By default, Spring Boot applications run as a `cluster_operator` role-based user in {pcf-name} when the app is bound By default, Spring Boot applications run as a `cluster_operator` role-based user in {pcf-name} when the application
to a {pcc-name} service instance. is bound to a {pcc-name} service instance.
A `cluster_operator` has full system privileges (that is, authorization) to do whatever that user wishes to involving A `cluster_operator` has full system privileges (that is, authorization) to do whatever that user wishes to involving
the PCC service instance. A `cluster_operator` has read and write access to all the data, can modify the schema the PCC service instance. A `cluster_operator` has read and write access to all the data, can modify the schema (for
(for example, create and destroy regions, add and remove indexes, change eviction or expiration policies, and so on), start and stop servers example, create and destroy Regions, add and remove Indexes, change eviction or expiration policies, and so on), start
in the PCC cluster, or even modify permissions. and stop servers in the PCC cluster, or even modify permissions.
.About cluster_operator as the default user .About cluster_operator as the default user
**** ****
One of the reasons why Spring Boot apps default to running as a `cluster_operator` is to allow configuration metadata to One of the reasons why Spring Boot applications default to running as a `cluster_operator` is to allow configuration
be sent from the client to the server. Enabling configuration metadata to be sent from the client to the server is a metadata to be sent from the client to the server. Enabling configuration metadata to be sent from the client to the
useful development-time feature and is as simple as annotating your main `@SpringBootApplication` class with server is a useful development-time feature and is as simple as annotating your main `@SpringBootApplication` class
the `@EnableClusterConfiguration` annotation: with the `@EnableClusterConfiguration` annotation:
.Using `@EnableClusterConfiguration` .Using `@EnableClusterConfiguration`
==== ====
@@ -46,28 +46,28 @@ class SpringBootApacheGeodeClientCacheApplication { }
---- ----
==== ====
With `@EnableClusterConfiguration`, region and OQL index configuration, metadata that is defined on the client can be sent to With `@EnableClusterConfiguration`, Region and OQL Index configuration metadata that is defined on the client can be
servers in the PCC cluster. {geode-name} requires matching regions by name on both the client and the servers in order for sent to servers in the PCC cluster. {geode-name} requires matching Regions by name on both the client and the servers
clients to send and receive data to and from the cluster. in order for clients to send and receive data to and from the cluster.
For example, when you declare the region where an application entity is persisted by using the `@Region` mapping For example, when you declare the Region where an application entity is persisted by using the `@Region` mapping
annotation and declare the `@EnableEntityDefinedRegions` annotation on the main `@SpringBootApplication` annotation and declare the `@EnableEntityDefinedRegions` annotation on the main `@SpringBootApplication` class
class in conjunction with the `@EnableClusterConfiguration` annotation, not only does SBDG create the required in conjunction with the `@EnableClusterConfiguration` annotation, not only does SBDG create the required client Region,
client region, but it also sends the configuration metadata for this region to the servers in the cluster to create but it also sends the configuration metadata for this Region to the servers in the cluster to create the matching,
the matching, required server region, where the data for your application entity is managed. required server Region, where the data for your application entity is managed.
**** ****
However... However...
> With great power comes great responsibility. - Uncle Ben > With great power comes great responsibility. - Uncle Ben
Not all Spring Boot applications that PCC need to change the schema or even modify data. Rather, certain apps Not all Spring Boot applications using PCC need to change the schema or even modify data. Rather, certain applications
may need only read access. Therefore, it is ideal to be able to configure your Spring Boot applications to run with may need only read access. Therefore, it is ideal to be able to configure your Spring Boot applications to run with
a different user at runtime other than the auto-configured `cluster_operator`, by default. a different user at runtime other than the auto-configured `cluster_operator`, by default.
A prerequisite for running a Spring Boot application by using PCC with a specific user is to create a user with restricted A prerequisite for running a Spring Boot application in PCC with a specific user is to create a user with restricted
permissions by using {pcf-name} AppsManager while provisioning the PCC service instance to which the Spring Boot app permissions by using {pcf-name} AppsManager while provisioning the PCC service instance to which the Spring Boot
is bound. application is bound.
Configuration metadata for the PCC service instance might appear as follows: Configuration metadata for the PCC service instance might appear as follows:
@@ -114,11 +114,11 @@ Configuration metadata for the PCC service instance might appear as follows:
---- ----
==== ====
In the PCC service instance configuration metadata shown in the preceding example, we see a `guest` user with the `read-only-user` role. In the PCC service instance configuration metadata shown in the preceding example, we see a `guest` user with
If the `read-only-user` role is properly configured with read-only permissions as the name implies, we could the `read-only-user` role. If the `read-only-user` role is properly configured with read-only permissions as the name
configure our Spring Boot application to run as `guest` with read-only access: implies, we could configure our Spring Boot application to run as `guest` with read-only access:
.Configuring a Spring Boot app to run as a specific user .Configuring a Spring Boot application to run as a specific user
==== ====
[source,properties] [source,properties]
---- ----
@@ -129,30 +129,31 @@ spring.data.gemfire.security.username=guest
==== ====
TIP: The `spring.data.gemfire.security.username` property corresponds directly to the SDG `@EnableSecurity` annotation's TIP: The `spring.data.gemfire.security.username` property corresponds directly to the SDG `@EnableSecurity` annotation's
`securityUsername` attribute. `securityUsername` attribute. See the
See the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#securityUsername--[Javadoc] {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#securityUsername--[Javadoc]
for more details. for more details.
The `spring.data.gemfire.security.username` property is the same property used by Spring Data for {geode-name} (SDG) to The `spring.data.gemfire.security.username` property is the same property used by Spring Data for {geode-name} (SDG) to
configure the runtime user of your Spring Data application when you connect to an externally managed {geode-name} cluster. configure the runtime user of your Spring Data application when you connect to an externally managed {geode-name}
cluster.
In this case, SBDG uses the configured username to look up the authentication credentials of the user to set In this case, SBDG uses the configured username to look up the authentication credentials of the user to set
the username and password used by the Spring Boot `ClientCache` app when connecting to PCC while running in PCF. the username and password used by the Spring Boot `ClientCache` application when connecting to PCC while running in PCF.
If the username is not valid, an `IllegalStateException` is thrown. If the username is not valid, an `IllegalStateException` is thrown.
By using {spring-boot-docs-html}/#boot-features-profiles[Spring profiles], it would be a simple matter to configure By using {spring-boot-docs-html}/#boot-features-profiles[Spring profiles], it would be a simple matter to configure
the Spring Boot application to run with a different user depending on environment. the Spring Boot application to run with a different user depending on environment.
See the {pcc-name} documentation on {pivotal-cloudcache-docs}/security.html[Security] for configuring users with See the {pcc-name} documentation on {pivotal-cloudcache-docs}/security.html[security] for configuring users with
assigned roles and permissions. assigned roles and permissions.
[[cloudfoundry-cloudcache-security-auth-autoconfiguration-override]] [[cloudfoundry-cloudcache-security-auth-autoconfiguration-override]]
==== Overriding Authentication Auto-configuration ==== Overriding Authentication Auto-configuration
It should be generally understood that auto-configuration for client authentication is available only for managed It should be understood that auto-configuration for client authentication is available only for managed environments,
environments, such as {pcf-name}. When running in externally managed environments, you must explicitly set a username such as {pcf-name}. When running in externally managed environments, you must explicitly set a username and password
and password to authenticate, as described in <<geode-security-auth-clients-non-managed>>. to authenticate, as described in <<geode-security-auth-clients-non-managed>>.
To completely override the auto-configuration of client authentication, you can set both a username and a password: To completely override the auto-configuration of client authentication, you can set both a username and a password:
@@ -167,21 +168,21 @@ spring.data.gemfire.security.password=MyPassword
---- ----
==== ====
In this case, SBDG's auto-configuration for authentication is effectively disabled and security credentials In this case, SBDG's auto-configuration for authentication is effectively disabled and security credentials are not
are not extracted from the environment. extracted from the environment.
[[cloudfoundry-cloudcache-serviceinstance-targeting]] [[cloudfoundry-cloudcache-serviceinstance-targeting]]
=== Targeting Specific {pcc-name} Service Instances === Targeting Specific {pcc-name} Service Instances
It is possible to provision multiple instances of the {pcc-name} service in your {pcf-name} environment. You can then It is possible to provision multiple instances of the {pcc-name} service in your {pcf-name} environment. You can then
bind multiple PCC service instances to your Spring Boot app. bind multiple PCC service instances to your Spring Boot application.
However, Spring Boot for {geode-name} (SBDG) only auto-configures one PCC service instance for your Spring Boot However, Spring Boot for {geode-name} (SBDG) only auto-configures one PCC service instance for your Spring Boot
application. This does not mean that it is not possible to use multiple PCC service instances with your Spring Boot app, application. This does not mean that it is not possible to use multiple PCC service instances with your Spring Boot
just that SBDG only auto-configures one service instance for you. application, just that SBDG only auto-configures one service instance for you.
You must select which PCC service instance your Spring Boot app automatically auto-configures for you when you have You must select which PCC service instance your Spring Boot application automatically auto-configures for you when
multiple instances and want to target a specific PCC service instance to use. you have multiple instances and want to target a specific PCC service instance to use.
To do so, declare the following SBDG property in Spring Boot `application.properties`: To do so, declare the following SBDG property in Spring Boot `application.properties`:
@@ -198,10 +199,10 @@ spring.boot.data.gemfire.cloud.cloudfoundry.service.cloudcache.name=pccServiceIn
The `spring.boot.data.gemfire.cloud.cloudfoundry.service.cloudcache.name` property tells SBDG which PCC service instance The `spring.boot.data.gemfire.cloud.cloudfoundry.service.cloudcache.name` property tells SBDG which PCC service instance
to auto-configure. to auto-configure.
If the PCC service instance identified by the property does not exist, SBDG throws If the PCC service instance identified by the property does not exist, SBDG throws an `IllegalStateException`
an `IllegalStateException` stating the PCC service instance by name could not be found. stating the PCC service instance by name could not be found.
If you did not set the property and your Spring Boot app is bound to multiple PCC service instances, If you did not set the property and your Spring Boot application is bound to multiple PCC service instances,
SBDG auto-configures the first PCC service instance it finds by name, alphabetically. SBDG auto-configures the first PCC service instance it finds by name, alphabetically.
If you did not set the property and no PCC service instance is found, SBDG logs a warning. If you did not set the property and no PCC service instance is found, SBDG logs a warning.
@@ -209,8 +210,8 @@ If you did not set the property and no PCC service instance is found, SBDG logs
[[cloudfoundry-cloudcache-multiinstance-using]] [[cloudfoundry-cloudcache-multiinstance-using]]
=== Using Multiple {pcc-name} Service Instances === Using Multiple {pcc-name} Service Instances
If you want to use multiple PCC service instances with your Spring Boot application, you need to configure If you want to use multiple PCC service instances with your Spring Boot application, you need to configure multiple
multiple connection `Pools` connected to each PCC service instance used by your Spring Boot application. connection `Pools` connected to each PCC service instance used by your Spring Boot application.
The configuration would be similar to the following: The configuration would be similar to the following:
@@ -234,7 +235,7 @@ class PccConfiguration {
You would then externalize the configuration for the individually declared `Pools` in Spring Boot You would then externalize the configuration for the individually declared `Pools` in Spring Boot
`application.properties`: `application.properties`:
.Configuring Pool Locator connection endpoints .Configuring Locator-based Pool connections
==== ====
[source,properties] [source,properties]
---- ----
@@ -250,13 +251,13 @@ NOTE: Though less common, you can also configure the `Pool` of connections to ta
by setting the `spring.data.gemfire.pool.<named-pool>.severs` property. by setting the `spring.data.gemfire.pool.<named-pool>.severs` property.
TIP: Keep in mind that properties in Spring Boot `application.properties` can refer to other properties: TIP: Keep in mind that properties in Spring Boot `application.properties` can refer to other properties:
`property=$\{otherProperty}`. This lets you further externalize properties by using Java system properties `property=$\{otherProperty}`. This lets you further externalize properties by using Java System properties
or environment variables. or environment variables.
A client region is then assigned the pool of connections that are used to send data to and from A client Region is then assigned the Pool of connections that are used to send data to and from the specific
the specific PCC service instance (cluster): PCC service instance (cluster):
.Assigning a pool to a client region .Assigning a Pool to a client Region
==== ====
[source,java] [source,java]
---- ----
@@ -279,8 +280,8 @@ class GeodeConfiguration {
---- ----
==== ====
You can configure as many pools and client regions as your application needs. Again, the `Pool` determines You can configure as many Pools and client Regions as your application needs. Again, the `Pool` determines
the {pcc-name} service instance and cluster in which the data for the client region resides. the {pcc-name} service instance and cluster in which the data for the client Region resides.
NOTE: By default, SBDG configures all `Pools` declared in a Spring Boot `ClientCache` application to connect to NOTE: By default, SBDG configures all `Pools` declared in a Spring Boot `ClientCache` application to connect to
and use a single PCC service instance. This may be a targeted PCC service instance when you use the and use a single PCC service instance. This may be a targeted PCC service instance when you use the
@@ -290,11 +291,11 @@ as discussed <<cloudfoundry-cloudcache-multiinstance-using,earlier>>.
[[cloudfoundry-geode]] [[cloudfoundry-geode]]
=== Hybrid {pcf-name} and {geode-name} Spring Boot Applications === Hybrid {pcf-name} and {geode-name} Spring Boot Applications
Sometimes, it is desirable to deploy (that is, "`push`") and run your Spring Boot applications in {pcf-name} but still Sometimes, it is desirable to deploy (that is, `cf push`) and run your Spring Boot applications in {pcf-name}
connect your Spring Boot applications to an externally managed, standalone {geode-name} cluster. but still connect your Spring Boot applications to an externally managed, standalone {geode-name} cluster.
Spring Boot for {geode-name} (SBDG) makes this a non-event and honors its "`little to no code or configuration changes Spring Boot for {geode-name} (SBDG) makes this a non-event and honors its "_little to no code or configuration changes
necessary`" goal. Regardless of your runtime choice, it should "`just work!`" necessary_" goal. Regardless of your runtime choice, it should just work!
To help guide you through this process, we cover the following topics: To help guide you through this process, we cover the following topics:
@@ -307,24 +308,24 @@ To help guide you through this process, we cover the following topics:
[[cloudfoundry-geode-pcfdev]] [[cloudfoundry-geode-pcfdev]]
==== Running PCFDev ==== Running PCFDev
For this exercise, we use https://pivotal.io/pcf-dev[PCF Dev]. For this exercise, we use https://docs.pivotal.io/pcf-dev/install-osx.html[PCF Dev].
PCF Dev, much like PCF, is an elastic application runtime for deploying, running, and managing your Spring Boot PCF Dev, much like PCF, is an elastic application runtime for deploying, running, and managing your Spring Boot
applications. However, it does so in the confines of your local development environment -- that is, your workstation. applications. However, it does so in the confines of your local development environment -- that is, your workstation.
Additionally, PCF Dev provides several services, such as MySQL, Redis, and RabbitMQ. Additionally, PCF Dev provides several services, such as MySQL, Redis, and RabbitMQ. You Spring Boot application
You Spring Boot application can bind and use these services to accomplish its tasks. can bind to and use these services to accomplish its tasks.
However, PCF Dev lacks the {pcc-name} service that is available in PCF. This is actually ideal for this exercise, However, PCF Dev lacks the {pcc-name} service that is available in PCF. This is actually ideal for this exercise since
since we are trying to build and run Spring Boot applications in a PCF environment but connect to an externally managed, we are trying to build and run Spring Boot applications in a PCF environment but connect to an externally managed,
standalone {geode-name} cluster. standalone {geode-name} cluster.
As a prerequisite, you need to follow the steps outlined in the As a prerequisite, you need to follow the steps outlined in the
https://pivotal.io/platform/pcf-tutorials/getting-started-with-pivotal-cloud-foundry-dev/introduction[tutorial] https://pivotal.io/platform/pcf-tutorials/getting-started-with-pivotal-cloud-foundry-dev/introduction[tutorial]
to get PCF Dev set up and running on your workstation. to get PCF Dev set up and running on your workstation.
To run PCF Dev, execute the following `cf` CLI command, replacing the path to the TGZ file To run PCF Dev, execute the following `cf` CLI command, replacing the path to the TGZ file with the file you acquired
with the file you acquired from the https://network.pivotal.io/products/pcfdev[download]: from the https://network.pivotal.io/products/pcfdev[download]:
.Start PCF Dev .Start PCF Dev
==== ====
@@ -394,17 +395,17 @@ You can also access the https://apps.dev.cfdev.sh/[PCF Dev Apps Manager] tool fr
https://apps.dev.cfdev.sh/ https://apps.dev.cfdev.sh/
Apps Manager provides a nice UI to manage your org, space, services, and apps. It lets you push and update apps, Apps Manager provides a nice UI to manage your org, space, services and apps. It lets you push and update apps,
create services, bind apps to the services, and start and stop your deployed applications, among many other things. create services, bind apps to the services, and start and stop your deployed applications, among many other things.
[[cloudfoundry-geode-cluster]] [[cloudfoundry-geode-cluster]]
==== Running an {geode-name} Cluster ==== Running an {geode-name} Cluster
Now that PCF Dev is set up and running, you need to start an external, standalone {geode-name} cluster to which our Spring Boot Now that PCF Dev is set up and running, you need to start an external, standalone {geode-name} cluster to which our
application connects and use it to manage its data. Spring Boot application connects and uses to manage its data.
You need to install a {apache-geode-website}/releases/[distribution] of {geode-name} on your workstation. You need to install a {apache-geode-website}/releases/[distribution] of {geode-name} on your computer. Then you must
Then you must set the `$GEODE` environment variable. It is also convenient to add `$GEODE/bin` to your system `$PATH`. set the `$GEODE` environment variable. It is also convenient to add `$GEODE/bin` to your system `$PATH`.
Afterward, you can launch the Geode Shell (_Gfsh_) tool: Afterward, you can launch the Geode Shell (_Gfsh_) tool:
@@ -437,17 +438,17 @@ include::{docs-resources-dir}/geode/bin/start-cluster.gfsh[]
---- ----
==== ====
The `start-cluster.gfsh` shell script starts one Geode locator and one Geode server. The `start-cluster.gfsh` shell script starts one Geode Locator and one Geode server.
A locator is used by clients to discover and connect to servers in the cluster to manage its data. A locator A Locator is used by clients to discover and connect to servers in a cluster to manage its data. A Locator is also used
is also used by new servers that join a cluster as peer members, which lets the cluster be elastically scaled out by new servers that join a cluster as peer members, which lets the cluster be elastically scaled out (or scaled down,
(or scaled down, as needed). A Geode server stores the data for the application. as needed). A Geode server stores the data for the application.
You can start as many locators or servers as necessary to meet the availability and load demands of your application. You can start as many Locators or servers as necessary to meet the availability and load demands of your application.
The more locators and servers your cluster has, the more resilient it is to failure. However, you should The more Locators and servers your cluster has, the more resilient it is to failure. However, you should size your
size your cluster accordingly, based on your application's needs, since there is overhead relative to the cluster size. cluster accordingly, based on your application's needs, since there is overhead relative to the cluster size.
You see output similar to the following when starting the locator and server: You see output similar to the following when starting the Locator and server:
.Starting the {geode-name} cluster .Starting the {geode-name} cluster
==== ====
@@ -515,8 +516,8 @@ No Regions Found
---- ----
==== ====
This is deliberate, since we are going to let the application drive its schema structure, both on the client (app) This is deliberate, since we are going to let the application drive its schema structure, both on the client
as well as on the server side (cluster). We cover this in more detail later in this chapter. (application) as well as on the server-side (cluster). We cover this in more detail later in this chapter.
[[cloudfoundry-geode-cups]] [[cloudfoundry-geode-cups]]
==== Creating a User-Provided Service ==== Creating a User-Provided Service
@@ -524,9 +525,9 @@ as well as on the server side (cluster). We cover this in more detail later in t
Now that we have PCF Dev and a small {geode-name} cluster up and running, it is time to create a user-provided service Now that we have PCF Dev and a small {geode-name} cluster up and running, it is time to create a user-provided service
to the external, standalone {geode-name} cluster that we started in <<cloudfoundry-geode-cluster,step 2>>. to the external, standalone {geode-name} cluster that we started in <<cloudfoundry-geode-cluster,step 2>>.
As mentioned, PCF Dev offers the MySQL, Redis and RabbitMQ services (among others). However, to use {geode-name} in As mentioned, PCF Dev offers MySQL, Redis and RabbitMQ services (among others). However, to use {geode-name} in the same
the same capacity as you would {pcc-name} when running in a production-grade PCF environment, you need to create a capacity as you would {pcc-name} when running in a production-grade PCF environment, you need to create a user-provided
user-provided service for the standalone {geode-name} cluster. service for the standalone {geode-name} cluster.
To do so, run the following `cf` CLI command: To do so, run the following `cf` CLI command:
@@ -541,8 +542,8 @@ $ cf cups <service-name> -t "gemfire, cloudcache, database, pivotal" -p '<servic
NOTE: It is important that you specify the tags (`gemfire`, `cloudcache`, `database`, `pivotal`) exactly as shown NOTE: It is important that you specify the tags (`gemfire`, `cloudcache`, `database`, `pivotal`) exactly as shown
in the preceding `cf` CLI command. in the preceding `cf` CLI command.
The argument passed to the `-p` command-line option is a JSON document (object) containing the credentials The argument passed to the `-p` command-line option is a JSON document (object) containing the credentials for our
for our user-provided service. user-provided service.
The JSON object is as follows: The JSON object is as follows:
@@ -569,17 +570,18 @@ cf cups apacheGeodeService -t "gemfire, cloudcache, database, pivotal" \
---- ----
==== ====
We replaced the `<hostname>` placeholder tag with the IP address of our external {geode-name} locator. You can find the IP address We replaced the `<hostname>` placeholder with the IP address of our standalone {geode-name} Locator. You can find
in the _Gfsh_ `start locator` output shown in the preceding example. the IP address in the Gfsh `start locator` command output shown in the preceding example.
Additionally, the `<port>` placeholder tag has been replaced with the default Locator port, `10334`, Additionally, the `<port>` placeholder has been replaced with the default Locator port, `10334`,
Finally, we set the `username` and `password` accordingly. Finally, we set the `username` and `password` accordingly.
TIP: Spring Boot for {geode-name} (SBDG) provides template files in the `{docs-dir}/src/main/resources` directory. TIP: Spring Boot for {geode-name} (SBDG) provides template files in the `{docs-dir}/src/main/resources` directory.
Once the service has been created, you can query the details from the `cf` CLI: Once the service has been created, you can query the details of the service from the `cf` CLI:
.Query the CF Dev Services
==== ====
[source,txt] [source,txt]
---- ----
@@ -607,17 +609,17 @@ You can also view the "apacheGeodeService" from Apps Manager, starting from the
image::{images-dir}/pcfdev-appsmanager-org-space-services.png[] image::{images-dir}/pcfdev-appsmanager-org-space-services.png[]
By clicking on the "apacheGeodeService" service entry in the table, you can get all the service details, By clicking on the "apacheGeodeService" service entry in the table, you can get all the service details, such as
such as the bound apps: the bound apps:
image::{images-dir}/pcfdev-appsmanager-org-space-service-boundapps.png[] image::{images-dir}/pcfdev-appsmanager-org-space-service-boundapps.png[]
You can also view and set the onfiguration: You can also view and set the configuration:
image::{images-dir}/pcfdev-appsmanager-org-space-service-configuration.png[] image::{images-dir}/pcfdev-appsmanager-org-space-service-configuration.png[]
This brief section did not cover all the capabilities of the Apps Manager. This brief section did not cover all the capabilities of the Apps Manager. We suggest you explore its UI to see all
We suggest you explore its UI to see all that is possible. that is possible.
TIP: You can learn more about CUPS in the TIP: You can learn more about CUPS in the
{pivotal-cloudfoundry-docs}/devguide/services/user-provided.html[PCF documentation]. {pivotal-cloudfoundry-docs}/devguide/services/user-provided.html[PCF documentation].
@@ -625,14 +627,14 @@ TIP: You can learn more about CUPS in the
[[cloudfoundry-geode-app]] [[cloudfoundry-geode-app]]
==== Push and Bind a Spring Boot application ==== Push and Bind a Spring Boot application
Now it is time to push a Spring Boot application to PCF Dev and bind the app to the `apacheGeodeService`. Now it is time to push a Spring Boot application to PCF Dev and bind the application to the `apacheGeodeService`.
Any Spring Boot `ClientCache` application that uses SBDG works for this purpose. For this example, we use Any Spring Boot `ClientCache` application that uses SBDG works for this purpose. For this example, we use the
the https://github.com/jxblum/PCCDemo/tree/sbdg-doc-ref[PCCDemo] application, which is available in GitHub. https://github.com/jxblum/PCCDemo/tree/sbdg-doc-ref[PCCDemo] application, which is available in GitHub.
After cloning the project to your workstation, you must perform a build to produce the artifact to push to PCF Dev: After cloning the project to your computer, you must run a build to produce the artifact to push to PCF Dev:
.Build the PCCDemo app .Build the PCCDemo application
==== ====
[source,txt] [source,txt]
---- ----
@@ -640,9 +642,9 @@ $ mvn clean package
---- ----
==== ====
Then you can push the app to PCF Dev with the following `cf` CLI command: Then you can push the application to PCF Dev with the following `cf` CLI command:
.Push app to PCF Dev .Push the application to PCF Dev
==== ====
[source,txt] [source,txt]
---- ----
@@ -650,9 +652,9 @@ $ cf push boot-pcc-demo -u none --no-start -p target/client-0.0.1-SNAPSHOT.jar
---- ----
==== ====
Once the app has been successfully deployed to PCF Dev, you can get app details: Once the application has been successfully deployed to PCF Dev, you can get the application details:
.Details for deployed app .Get details for the deployed application
==== ====
[source,txt] [source,txt]
---- ----
@@ -688,9 +690,9 @@ There are no running instances of this process.
---- ----
==== ====
You can bind the PPCDemo app to the `apacheGeodeService` using the `cf` CLI command: You can bind the PPCDemo application to the `apacheGeodeService` using the `cf` CLI command:
.Bind app to apacheGeodeService using CLI .Bind application to `apacheGeodeService` using CLI
==== ====
[source,txt] [source,txt]
---- ----
@@ -698,10 +700,10 @@ cf bind-service boot-pcc-demo apacheGeodeService
---- ----
==== ====
Alternatively, you can create a YAML file (`manifest.yml` in `src/main/resources`) that contains the Alternatively, you can create a YAML file (`manifest.yml` in `src/main/resources`) that contains
deployment descriptor: the deployment descriptor:
.Example YAML deployment descriptor file .Example YAML deployment descriptor
==== ====
[source,yml] [source,yml]
---- ----
@@ -718,37 +720,37 @@ applications:
---- ----
==== ====
You can also use Apps Manager to view app details and bind and unbind additional services. Start by navigating to You can also use Apps Manager to view application details and bind and unbind additional services.
the `App` tab under your org and space: Start by navigating to the `App` tab under your org and space:
image::{images-dir}/pcfdev-appsmanager-org-space-apps.png[] image::{images-dir}/pcfdev-appsmanager-org-space-apps.png[]
From there, you can click on the desired app and navigate to the `Overview`: From there, you can click on the desired application and navigate to the `Overview`:
image::{images-dir}/pcfdev-appsmanager-org-space-app-overview.png[] image::{images-dir}/pcfdev-appsmanager-org-space-app-overview.png[]
You can also review the app `Settings`. Specifically, we are looking at the configuration of the app once it is bound to You can also review the application `Settings`. Specifically, we are looking at the configuration of the applicatinon
the `apacheGeodeService`, as seen in the `VCAP_SERVICES` environment variable: once it is bound to the `apacheGeodeService`, as seen in the `VCAP_SERVICES` environment variable:
image::{images-dir}/pcfdev-appsmanager-org-space-app-settings-envvars.png[] image::{images-dir}/pcfdev-appsmanager-org-space-app-settings-envvars.png[]
This JSON document structure is not unlike the configuration used to bind your Spring Boot `ClientCache` application This JSON document structure is not unlike the configuration used to bind your Spring Boot `ClientCache` application
to the {pcc-name} service when deploying the same app to {pcf-name}. This is actually key if you want to minimize to the {pcc-name} service when deploying the same application to {pcf-name}. This is actually key if you want to
the amount of boilerplate code and configuration changes when you migrate between different CloudFoundry environments, minimize the amount of boilerplate code and configuration changes when you migrate between different CloudFoundry
even https://www.cloudfoundry.org/[Open Source CloudFoundry]. environments, even https://www.cloudfoundry.org/[Open Source CloudFoundry].
Again, SBDG's entire goal is to simply the effort for you to build, run, and manage your application, Again, SBDG's goal is to simply the effort for you to build, run, and manage your application, in whatever context
in whatever context your application lands, even if it changes later. If you follow the steps in this documentation, your application lands, even if it changes later. If you follow the steps in this documentation, you can realize
you can realize that goal. that goal.
[[cloudfoundry-geode-app-run]] [[cloudfoundry-geode-app-run]]
==== Running the Spring Boot application ==== Running the Spring Boot application
All that is left to do now is run the app. All that is left to do now is run the application.
You can start the PCCDemo app from the `cf` CLI by using the following command: You can start the PCCDemo application from the `cf` CLI by using the following command:
.Start the Spring Boot app .Start the Spring Boot application
==== ====
[source,txt] [source,txt]
---- ----
@@ -756,23 +758,23 @@ $ cf start boot-pcc-demo
---- ----
==== ====
Alternatively, you can also start the app from Apps Manager. This is convenient, since you can then tail and monitor Alternatively, you can also start the application from Apps Manager. This is convenient, since you can then tail
the application log file. and monitor the application log file.
image::{images-dir}/pcfdev-appsmanager-org-space-app-logs.png[] image::{images-dir}/pcfdev-appsmanager-org-space-app-logs.png[]
Once the app has started, you can click the https://boot-pcc-demo.dev.cfdev.sh/[VIEW APP] link Once the application has started, you can click the https://boot-pcc-demo.dev.cfdev.sh/[VIEW APP] link
in the upper right corner of the `APP` screen. in the upper right corner of the `APP` screen.
image::{images-dir}/PCCDemo-app-screenshot.png[] image::{images-dir}/PCCDemo-app-screenshot.png[]
You can navigate to any of the application Web Service, Controller endpoints. For example, if you know the ISBN You can navigate to any of the application Web Service, Controller endpoints. For example, if you know the ISBN
of a book, you can access it from the Web browser: of a book, you can access it from your Web browser:
image::{images-dir}/PCCDemo-app-book-by-isbn-screenshot.png[] image::{images-dir}/PCCDemo-app-book-by-isbn-screenshot.png[]
You can also access the same data from the Gfsh command-line tool. However, the first thing to observe You can also access the same data from the Gfsh command-line tool. However, the first thing to observe is that our
is that our application informed the cluster that it needed a region called `Books`: application informed the cluster that it needed a Region called `Books`:
.Books Region .Books Region
==== ====
@@ -819,12 +821,12 @@ Rows : 1
[[cloudfoundry-geode-summary]] [[cloudfoundry-geode-summary]]
=== Summary === Summary
The ability to deploy Spring Boot, {geode-name} `ClientCache` applications to {pcf-name} yet connect your app to an The ability to deploy Spring Boot, {geode-name} `ClientCache` applications to {pcf-name} yet connect your application to
externally managed, standalone {geode-name} cluster is powerful. an externally managed, standalone {geode-name} cluster is powerful.
Indeed, this is a useful arrangement and stepping stone for many users as they begin their journey towards Indeed, this is a useful arrangement and stepping stone for many users as they begin their journey towards Cloud-Native
Cloud-Native platforms such as {pcf-name} and using services such as {pcc-name}. platforms such as {pcf-name} and using services such as {pcc-name}.
Later, when you need to work with real (rather than sample) applications, you can migrate your Spring Boot applications to a fully Later, when you need to work with real (rather than sample) applications, you can migrate your Spring Boot applications
managed and production-grade {pcf-name} environment, and SBDG figures out what to do, leaving you to focus entirely to a fully managed and production-grade {pcf-name} environment, and SBDG figures out what to do, leaving you to focus
on your application. entirely on your application.

View File

@@ -1,8 +1,8 @@
[[geode-auto-configuration-annotations]] [[geode-auto-configuration-annotations]]
== Auto-configuration vs. Annotation-based configuration == Auto-configuration vs. Annotation-based configuration
:geode-name: {apache-geode-name} :geode-name: {apache-geode-name}
:vmw-gemfire-name: VMware Tanzu GemFire :vmw-gemfire-name: {pivotal-gemfire-name}
:vmw-tas-name: VMware Tanzu Application Service :vmw-tas-name: {pivotal-cloudfoundry-name}
The question most often asked is, "`What Spring Data for {geode-name} (SDG) annotations can I use, or must I use, when The question most often asked is, "`What Spring Data for {geode-name} (SDG) annotations can I use, or must I use, when
@@ -16,29 +16,29 @@ which shows the auto-configuration provided by Spring Boot for {geode-name} in a
[[geode-autoconfiguration-annotations-background]] [[geode-autoconfiguration-annotations-background]]
=== Background === Background
To help answer this question, we must start by reviewing the complete collection of available Spring Data for {geode-name} To help answer this question, you must start by reviewing the complete collection of available Spring Data for
(SDG) annotations. These annotations are provided in the {geode-name} (SDG) annotations. These annotations are provided in the
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-summary.html[`org.springframework.data.gemfire.config.annotation`] {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-summary.html[`org.springframework.data.gemfire.config.annotation`]
package. Most of the pertinent annotations begin with `@Enable...`, except for the base annotations: package. Most of the essential annotations begin with `@Enable...`, except for the base annotations:
`@ClientCacheApplication`, `@PeerCacheApplication`, and `@CacheServerApplication`. `@ClientCacheApplication`, `@PeerCacheApplication` and `@CacheServerApplication`.
By extension, Spring Boot for {geode-name} (SBDG) builds on SDG's annotation-based configuration model to implement By extension, Spring Boot for {geode-name} (SBDG) builds on SDG's annotation-based configuration model to implement
auto-configuration and apply Spring Boot's core concepts, such as "`convention over configuration`", letting auto-configuration and apply Spring Boot's core concepts, such as "`convention over configuration`", letting
{geode-name} applications be built with Spring Boot reliably, quickly, and easily. {geode-name} applications be built with Spring Boot reliably, quickly, and easily.
SDG provides this Annotation-based configuration model to, first and foremost, give application developers "`choice`" SDG provides this annotation-based configuration model to, first and foremost, give application developers "`choice`"
when building Spring applications with {geode-name}. SDG makes no assumptions about what application developers are when building Spring applications with {geode-name}. SDG makes no assumptions about what application developers are
trying to create and fails fast anytime the configuration is ambiguous, giving users immediate feedback. trying to create and fails fast anytime the configuration is ambiguous, giving users immediate feedback.
Second, SDG's annotations were meant to get application developers up and running quickly and reliably with ease. SDG Second, SDG's annotations were meant to get application developers up and running quickly and reliably with ease. SDG
accomplishes this by applying sensible defaults so that application developers need not know, or even have to learn, accomplishes this by applying sensible defaults so that application developers need not know, or even have to learn, all
all the intricate configuration details and tooling provided by {geode-name} to accomplish simple tasks, such as building a the intricate configuration details and tooling provided by {geode-name} to accomplish simple tasks, such as building a
prototype. prototype.
So, SDG is all about "`choice`" and SBDG is all about "`convention`". Together these frameworks provide application So, SDG is all about "`choice`" and SBDG is all about "`convention`". Together these frameworks provide application
developers with convenience and reliability to move quickly and easily. developers with convenience and ease to move quickly and reliably.
To learn more about the motivation behind SDG's Annotation-based configuration model, see the To learn more about the motivation behind SDG's annotation-based configuration model, see the
{spring-data-gemfire-docs-html}/#bootstrap-annotation-config-introduction[Reference Documentation]. {spring-data-gemfire-docs-html}/#bootstrap-annotation-config-introduction[Reference Documentation].
[[geode-autoconfiguration-annotations-conventions]] [[geode-autoconfiguration-annotations-conventions]]
@@ -49,18 +49,18 @@ Currently, SBDG provides auto-configuration for the following features:
* `ClientCache` * `ClientCache`
* Caching with Spring's cache abstraction * Caching with Spring's cache abstraction
* Continuous Query * Continuous Query
* Function execution and implementation * Function Execution and Implementation
* Logging * Logging
* PDX * PDX
* `GemfireTemplate` * `GemfireTemplate`
* Spring Data repositories * Spring Data Repositories
* Security (Client/server auth and SSL) * Security (Client/server auth and SSL)
* Spring Session * Spring Session
This means the following SDG Annotations are not required to use the features above: This means the following SDG annotations are not required to use the features above:
* `@ClientCacheApplication` * `@ClientCacheApplication`
* `@EnableGemfireCaching` (or by using Spring Framework's `@EnableCaching`) * `@EnableGemfireCaching` (or by using Spring Framework's `@EnableCaching` annotation)
* `@EnableContinuousQueries` * `@EnableContinuousQueries`
* `@EnableGemfireFunctionExecutions` * `@EnableGemfireFunctionExecutions`
* `@EnableGemfireFunctions` * `@EnableGemfireFunctions`
@@ -72,7 +72,7 @@ This means the following SDG Annotations are not required to use the features ab
* `@EnableGemFireHttpSession` * `@EnableGemFireHttpSession`
Since SBDG auto-configures these features for you, the above annotations are not strictly required. Typically, you Since SBDG auto-configures these features for you, the above annotations are not strictly required. Typically, you
would only declare one of theses annotations when you want to "`override`" Spring Boot's conventions, as expressed in would only declare one of these annotations when you want to "`override`" Spring Boot's conventions, as expressed in
auto-configuration, and "`customize`" the behavior of the feature. auto-configuration, and "`customize`" the behavior of the feature.
[[geode-autoconfiguration-annotations-overriding]] [[geode-autoconfiguration-annotations-overriding]]
@@ -83,37 +83,38 @@ In this section, we cover a few examples to make the behavior when overriding mo
[[geode-autoconfiguration-annotations-overriding-caches]] [[geode-autoconfiguration-annotations-overriding-caches]]
==== Caches ==== Caches
By default, SBDG provides you with a `ClientCache` instance. SBDG accomplishes this by annotating By default, SBDG provides you with a `ClientCache` instance. SBDG accomplishes this by annotating an auto-configuration
an auto-configuration class with `@ClientCacheApplication` internally. class with `@ClientCacheApplication` internally.
By convention, we assume most application developers' are developing Spring Boot applications by using By convention, we assume most application developers' are developing Spring Boot applications by using {geode-name}
{geode-name} as "`client`" applications in {geode-name}'s client/server topology. This is especially true as users as "`client`" applications in {geode-name}'s client/server topology. This is especially true as users migrate their
migrate their applications to a managed cloud environment. applications to a managed cloud environment.
Still, you can "override" the default settings and declare your Spring applications to be actual peer `Cache` Still, you can "`override`" the default settings (convention) and declare your Spring applications to be actual peer
members of a cluster, instead: `Cache` members (nodes) of a {geode-name} cluster, instead:
.Spring Boot, {geode-name} Peer `Cache` Application
==== ====
[source,java] [source,java]
---- ----
@SpringBootApplication @SpringBootApplication
@CacheServerApplication @CacheServerApplication
class MySpringBootPeerCacheServerApplication { } class SpringBootApacheGeodePeerCacheServerApplication { }
---- ----
==== ====
By declaring the `@CacheServerApplication` annotation, you effectively override the SBDG default. Therefore, SBDG By declaring the `@CacheServerApplication` annotation, you effectively override the SBDG default. Therefore, SBDG
does not provide a `ClientCache` instance, because you have informed SBDG of exactly what you want: a peer `Cache` does not provide you with a `ClientCache` instance by default, because you have informed SBDG of exactly what you want:
instance hosting an embedded `CacheServer` that allows client connections. a peer `Cache` instance hosting an embedded `CacheServer` that allows client connections.
However, you then might ask, "`Well, how do I customize the `ClientCache` instance when developing client applications However, you then might ask, "`Well, how do I customize the `ClientCache` instance when developing client applications
without explicitly declaring the `@ClientCacheApplication` annotation?`" without explicitly declaring the `@ClientCacheApplication` annotation?`"
First, you can "`customize`" the `ClientCache` instance by explicitly declaring the First, you can "`customize`" the `ClientCache` instance by explicitly declaring the `@ClientCacheApplication` annotation
`@ClientCacheApplication` annotation in your Spring Boot application configuration and setting specific attributes in your Spring Boot application configuration and setting specific attributes as needed. However, you should be aware
as needed. However, you should be aware that, by explicitly declaring this annotation, (or, by default, any of the other that, by explicitly declaring this annotation, (or, by default, any of the other auto-configured annotations), you
auto-configured annotations), you assume all the responsibility that comes with it, since you have assume all the responsibility that comes with it, since you have effectively overridden the auto-configuration. One
effectively overridden the auto-configuration. One example of this is security, which we touch on more later. example of this is security, which we touch on more later.
The most ideal way to "`customize`" the configuration of any feature is by way of the well-known and documented The most ideal way to "`customize`" the configuration of any feature is by way of the well-known and documented
<<geode-configuration-metadata,properties>>, specified in Spring Boot `application.properties` (the "`convention`"), <<geode-configuration-metadata,properties>>, specified in Spring Boot `application.properties` (the "`convention`"),
@@ -124,8 +125,8 @@ See the <<geode-clientcache-applications,Reference Guide>> for more detail.
[[geode-autoconfiguration-annotations-overriding-security]] [[geode-autoconfiguration-annotations-overriding-security]]
==== Security ==== Security
As the `@ClientCacheApplication` annotation, the `@EnableSecurity` annotation is not strictly required, unless As with the `@ClientCacheApplication` annotation, the `@EnableSecurity` annotation is not strictly required, unless you
you want to override and customize the defaults. want to override and customize the defaults.
Outside a managed environment, the only security configuration required is specifying a username and password. You do Outside a managed environment, the only security configuration required is specifying a username and password. You do
this by using the well-known and documented SDG username and password properties in Spring Boot `application.properties`: this by using the well-known and documented SDG username and password properties in Spring Boot `application.properties`:
@@ -139,50 +140,49 @@ spring.data.gemfire.security.password=Secret
---- ----
==== ====
You need not explicitly declare the `@EnableSecurity` annotation just to specify security configuration You need not explicitly declare the `@EnableSecurity` annotation just to specify security configuration (such as
(such as username and password). username and password).
Inside a managed environment, such as the {vmw-tas-name} (TAS) when using {vmw-gemfire-name}, SBDG is able to introspect Inside a managed environment, such as the {vmw-tas-name} when using {vmw-gemfire-name}, SBDG is able to introspect
the environment and configure security (auth) completely without the need to specify any configuration, usernames the environment and configure security (auth) completely without the need to specify any configuration, usernames
and passwords, or otherwise. This is due, in part, because PCF supplies the security details in the VCAP environment and passwords, or otherwise. This is due, in part, because TAS supplies the security details in the VCAP environment
when the app is deployed to TAS and bound to services (such as {vmw-gemfire-name}). when the application is deployed to TAS and bound to services (such as {vmw-gemfire-name}).
So, in short, you need not explicitly declare the `@EnableSecurity` annotation (or the `@ClientCacheApplication`). So, in short, you need not explicitly declare the `@EnableSecurity` annotation (or `@ClientCacheApplication`).
However, if you do explicitly declare the `@ClientCacheApplication` or `@EnableSecurity` annotations, However, if you do explicitly declare the `@ClientCacheApplication` or `@EnableSecurity` annotations, you are now
you are now responsible for this configuration, and SBDG's auto-configuration no longer applies. responsible for this configuration, and SBDG's auto-configuration no longer applies.
While explicitly declaring `@EnableSecurity` makes more sense when "`overriding`" the SBDG Security auto-configuration, While explicitly declaring `@EnableSecurity` makes more sense when "`overriding`" the SBDG security auto-configuration,
explicitly declaring the `@ClientCacheApplication` annotation most likely makes less sense with regard to its impact explicitly declaring the `@ClientCacheApplication` annotation most likely makes less sense with regard to its impact
on security configuration. on security configuration.
This is entirely due to the internals of {geode-name}, because, in certain cases (such as security), not even Spring is able to This is entirely due to the internals of {geode-name}, because, in certain cases (such as security), not even Spring
completely shield you from the nuances of {geode-name}'s configuration. is able to completely shield you from the nuances of {geode-name}'s configuration. No framework can.
You must configure both auth and SSL before the cache instance (whether a `ClientCache` or a peer `Cache`) You must configure both auth and SSL before the cache instance (whether a `ClientCache` or a peer `Cache`) is created.
is created. This is because security is enabled and configured during the "`construction`" This is because security is enabled and configured during the "`construction`" of the cache. Also,, the cache pulls
of the cache. Also,, the cache pulls the configuration from JVM System properties that must be set before the cache the configuration from JVM System properties that must be set before the cache is constructed.
is constructed.
Structuring the "`exact`" order of the auto-configuration classes provided by SBDG when the classes are triggered, Structuring the "`exact`" order of the auto-configuration classes provided by SBDG when the classes are triggered, is no
is no small feat. Therefore, it should come as no surprise to learn that the security auto-configuration classes small feat. Therefore, it should come as no surprise to learn that the security auto-configuration classes in SBDG must
in SBDG must be triggered before the `ClientCache` auto-configuration class, which is why a `ClientCache` instance cannot be triggered before the `ClientCache` auto-configuration class, which is why a `ClientCache` instance cannot "`auto`"
"`auto`" authenticate properly in PCC when the `@ClientCacheApplication` is explicitly declared without some assistance. authenticate properly in PCC when the `@ClientCacheApplication` is explicitly declared without some assistance. In other
In other words you must also explicitly declare the `@EnableSecurity` annotation in this case, since you overrode the words you must also explicitly declare the `@EnableSecurity` annotation in this case, since you overrode the
auto-configuration of the cache and implicitly security as well. auto-configuration of the cache, and implicitly security, as well.
Again, this is due to the way security (auth) and SSL metadata must be supplied to {geode-name}. Again, this is due to the way security (auth) and SSL metadata must be supplied to {geode-name} on startup.
See the <<geode-security,Reference Guide>> for more details. See the <<geode-security,Reference Guide>> for more details.
[[geode-autoconfiguration-annotations-extension]] [[geode-autoconfiguration-annotations-extension]]
=== Extension === Extension
Most of the time, many of the other auto-configured annotations for CQ, Functions, PDX, Repositories, and so need not Most of the time, many of the other auto-configured annotations for CQ, Functions, PDX, Repositories, and so on need not
ever be declared explicitly. ever be declared explicitly.
Many of these features are enabled automatically by having SBDG or other libraries (such as Spring Session) Many of these features are enabled automatically by having SBDG or other libraries (such as Spring Session) on
on the classpath or are enabled based on other annotations applied to beans in the Spring `ApplicationContext`. the application classpath or are enabled based on other annotations applied to beans in the Spring `ApplicationContext`.
We review a few examples in the following sections. We review a few examples in the following sections.
@@ -190,8 +190,8 @@ We review a few examples in the following sections.
==== Caching ==== Caching
It is rarely, if ever, necessary to explicitly declare either the Spring Framework's `@EnableCaching` or the It is rarely, if ever, necessary to explicitly declare either the Spring Framework's `@EnableCaching` or the
SDG-specific `@EnableGemfireCaching` annotation in Spring configuration when you use SBDG. SBDG automatically "`enables`" SDG-specific `@EnableGemfireCaching` annotation in Spring configuration when you use SBDG. SBDG automatically
caching and configures the SDG `GemfireCacheManager` for you. enables caching and configures the SDG `GemfireCacheManager` for you.
You need only focus on which application service components are appropriate for caching: You need only focus on which application service components are appropriate for caching:
@@ -202,22 +202,22 @@ You need only focus on which application service components are appropriate for
@Service @Service
class CustomerService { class CustomerService {
@Autowired @Autowired
private CustomerRepository customerRepository; private CustomerRepository customerRepository;
@Cacheable("CustomersByName") @Cacheable("CustomersByName")
public Customer findBy(String name) { public Customer findBy(String name) {
return customerRepository.findByName(name); return customerRepository.findByName(name);
} }
} }
---- ----
==== ====
You need to create {geode-name} regions that back the caches declared in your application service You need to create {geode-name} Regions that back the caches declared in your application service components
components (`CustomersByName` in the preceding example) by using Spring's Caching Annotations (such as `@Cacheable`), or alternatively, (`CustomersByName` in the preceding example) by using Spring's caching annotations (such as `@Cacheable`),
JSR-107 JCache annotations (such as `@CacheResult`). or alternatively, JSR-107 JCache annotations (such as `@CacheResult`).
You can do that by defining each region explicitly or, more conveniently, you can use the following approach: You can do that by defining each Region explicitly or, more conveniently, you can use the following approach:
.Configuring Caches (Regions) .Configuring Caches (Regions)
==== ====
@@ -229,16 +229,16 @@ class Application { }
---- ----
==== ====
`@EnableCachingDefinedRegions` is optional, provided for convenience, and complementary to caching when used `@EnableCachingDefinedRegions` is optional, provided for convenience, and complementary to caching when used rather than
rather than being necessary. being necessary.
See the <<geode-caching-provider,Reference Guide>> for more detail. See the <<geode-caching-provider,Reference Guide>> for more detail.
[[geode-autoconfiguration-annotations-extension-cq]] [[geode-autoconfiguration-annotations-extension-cq]]
==== Continuous Query ==== Continuous Query
It is rarely, if ever, necessary to explicitly declare the SDG `@EnableContinuousQueries` annotation. Instead, It is rarely, if ever, necessary to explicitly declare the SDG `@EnableContinuousQueries` annotation. Instead, you
you should focus on defining your application queries and worry less about the plumbing. should focus on defining your application queries and worry less about the plumbing.
Consider the following example: Consider the following example:
@@ -272,8 +272,10 @@ See the <<geode-continuous-query,Reference Guide>> for more detail.
==== Functions ==== Functions
You rarely, if ever, need to explicitly declare either the `@EnableGemfireFunctionExecutions` You rarely, if ever, need to explicitly declare either the `@EnableGemfireFunctionExecutions`
or `@EnableGemfireFunctions` annotations. SBDG provides auto-configuration for both function implementations or `@EnableGemfireFunctions` annotations. SBDG provides auto-configuration for both Function implementations
and executions. You need to define the implementation: and executions.
You need to define the implementation:
.Function Implementation .Function Implementation
==== ====
@@ -282,10 +284,10 @@ and executions. You need to define the implementation:
@Component @Component
class GeodeFunctions { class GeodeFunctions {
@GemfireFunction @GemfireFunction
Object exampleFunction(Object arg) { Object exampleFunction(Object arg) {
// ... // ...
} }
} }
---- ----
==== ====
@@ -299,24 +301,25 @@ Then you need to define the execution:
@OnRegion(region = "Example") @OnRegion(region = "Example")
interface GeodeFunctionExecutions { interface GeodeFunctionExecutions {
Object exampleFunction(Object arg); Object exampleFunction(Object arg);
} }
---- ----
==== ====
SBDG automatically finds, configures, and registers function implementations (POJOs) in {geode-name} as proper SBDG automatically finds, configures, and registers Function implementations (POJOs) in {geode-name} as proper
`Functions` and creates execution proxies for the interfaces, which can then be injected into application service `Functions` and creates execution proxies for the interfaces, which can then be injected into application service
components to invoke the registered `Functions` without needing to explicitly declare the enabling annotations. components to invoke the registered `Functions` without needing to explicitly declare the enabling annotations.
The application function implementations and executions (interfaces) should exist below the `@SpringBootApplication` The application Function implementations (POJOs) and executions (interfaces) should exist below
annotated main class. the `@SpringBootApplication` annotated main class.
See the <<[geode-functions,Reference Guide>> for more detail. See the <<geode-functions,Reference Guide>> for more detail.
[[geode-autoconfiguration-annotations-extension-pdx]] [[geode-autoconfiguration-annotations-extension-pdx]]
==== PDX ==== PDX
You rarely, if ever, need to explicitly declare the `@EnablePdx` annotation, since SBDG auto-configures PDX You rarely, if ever, need to explicitly declare the `@EnablePdx` annotation, since SBDG auto-configures PDX by default.
by default. SBDG also automatically configures the SDG `MappingPdxSerializer` as the default `PdxSerializer`. SBDG also automatically configures the SDG `MappingPdxSerializer` as the default `PdxSerializer`.
It is easy to customize the PDX configuration by setting the appropriate <<geode-configuration-metadata,properties>> It is easy to customize the PDX configuration by setting the appropriate <<geode-configuration-metadata,properties>>
(search for "`PDX`") in Spring Boot `application.properties`. (search for "`PDX`") in Spring Boot `application.properties`.
@@ -326,10 +329,10 @@ See the <<geode-data-serialization,Reference Guide>> for more detail.
[[geode-autoconfiguration-annotations-extension-repositories]] [[geode-autoconfiguration-annotations-extension-repositories]]
==== Spring Data Repositories ==== Spring Data Repositories
You rarely, if ever, need to explicitly declare the `@EnableGemfireRepositories` annotation, since SBDG You rarely, if ever, need to explicitly declare the `@EnableGemfireRepositories` annotation, since SBDG auto-configures
auto-configures Spring Data (SD) repositories by default. Spring Data (SD) Repositories by default.
You need only define your repositories: You need only define your Repositories:
.Customer's Repository .Customer's Repository
==== ====
@@ -337,18 +340,18 @@ You need only define your repositories:
---- ----
interface CustomerRepository extends CrudRepository<Customer, Long> { interface CustomerRepository extends CrudRepository<Customer, Long> {
Customer findByName(String name); Customer findByName(String name);
} }
---- ----
==== ====
SBDG finds the repository interfaces defined in your application, proxies them, and registers them as beans SBDG finds the Repository interfaces defined in your application, proxies them, and registers them as beans in
in the Spring `ApplicationContext`. The repositories can be injected into other application service components. the Spring `ApplicationContext`. The Repositories can be injected into other application service components.
It is sometimes convenient to use the `@EnableEntityDefinedRegions` along with SD repositories to identify It is sometimes convenient to use the `@EnableEntityDefinedRegions` along with Spring Data Repositories to identify
the entities used by your application and define the regions used by the SD repository infrastructure to persist the entities used by your application and define the Regions used by the Spring Data Repository infrastructure to
the entity's state. The `@EnableEntityDefinedRegions` annotation is optional, provided for convenience, persist the entity's state. The `@EnableEntityDefinedRegions` annotation is optional, provided for convenience,
and complementary to the `@EnableGemfireRepositories` annotation. and complementary to the `@EnableGemfireRepositories` annotation.
See the <<geode-repositories,Reference Guide>> for more detail. See the <<geode-repositories,Reference Guide>> for more detail.
@@ -384,9 +387,8 @@ Most of the other annotations provided in SDG are focused on particular applicat
* `@EnableStatistics` * `@EnableStatistics`
* `@UseGemFireProperties` * `@UseGemFireProperties`
None of these annotations are necessary and none are auto-configured by SBDG. They are at your None of these annotations are necessary and none are auto-configured by SBDG. They are at your disposal when and if you
disposal you need them. This also means that none of these annotations are in conflict with need them. This also means that none of these annotations are in conflict with any SBDG auto-configuration.
any SBDG auto-configuration.
[[geode-autoconfiguration-annotations-summary]] [[geode-autoconfiguration-annotations-summary]]
=== Summary === Summary
@@ -394,12 +396,12 @@ any SBDG auto-configuration.
In conclusion, you need to understand where SDG ends and SBDG begins. It all begins with the auto-configuration In conclusion, you need to understand where SDG ends and SBDG begins. It all begins with the auto-configuration
provided by SBDG. provided by SBDG.
If a feature is not covered by SBDG's auto-configuration, you are responsible for enabling and configuring If a feature or function is not covered by SBDG's auto-configuration, you are responsible for enabling and configuring
the feature appropriately, as needed by your application (for example, `@EnableRedisServer`). the feature appropriately, as needed by your application (for example, `@EnableRedisServer`).
In other cases, you might also want to explicitly declare a complimentary annotation (such as `@EnableEntityDefinedRegions`) In other cases, you might also want to explicitly declare a complimentary annotation
for convenience, since SBDG provides no convention or "`opinion`". (such as `@EnableEntityDefinedRegions`) for convenience, since SBDG provides no convention or opinion.
In all remaining cases, it boils down to understanding how {geode-name} works under the hood. While we go to great In all remaining cases, it boils down to understanding how {geode-name} works under the hood. While we go to great
lengths to shield you from as many details as possible, it is not feasible or practical to address all matters, lengths to shield you from as many details as possible, it is not feasible or practical to address all matters, such as
such as cache creation and security. cache creation and security.

View File

@@ -9,8 +9,8 @@ annotations are implicitly declared by Spring Boot for {geode-name}'s (SBDG) aut
* `@ClientCacheApplication` * `@ClientCacheApplication`
* `@EnableGemfireCaching` (alternatively, Spring Framework's `@EnableCaching`) * `@EnableGemfireCaching` (alternatively, Spring Framework's `@EnableCaching`)
* `@EnableContinuousQueries` * `@EnableContinuousQueries`
* `@EnableGemfireFunctionExecutions`
* `@EnableGemfireFunctions` * `@EnableGemfireFunctions`
* `@EnableGemfireFunctionExecutions`
* `@EnableGemfireRepositories` * `@EnableGemfireRepositories`
* `@EnableLogging` * `@EnableLogging`
* `@EnablePdx` * `@EnablePdx`
@@ -19,35 +19,35 @@ annotations are implicitly declared by Spring Boot for {geode-name}'s (SBDG) aut
* `@EnableGemFireHttpSession` * `@EnableGemFireHttpSession`
NOTE: This means that you need not explicitly declare any of these annotations on your `@SpringBootApplication` class, NOTE: This means that you need not explicitly declare any of these annotations on your `@SpringBootApplication` class,
since they are provided by SBDG already. The only reason you would explicitly declare any of these annotations is since they are provided by SBDG already. The only reason you would explicitly declare any of these annotations is to
to _override_ Spring Boot's, and in particular, SBDG's auto-configuration. Otherwise, doing so is unnecessary. override Spring Boot's, and in particular, SBDG's auto-configuration. Otherwise, doing so is unnecessary.
TIP: You should read the chapter in Spring Boot's Reference documentation on TIP: You should read the chapter in Spring Boot's reference documentation on
{spring-boot-docs-html}/#using-boot-auto-configuration[auto-configuration]. {spring-boot-docs-html}/#using-boot-auto-configuration[auto-configuration].
TIP: You should review the chapter in Spring Data for {geode-name}'s (SDG) Reference documentation TIP: You should review the chapter in Spring Data for {geode-name}'s (SDG) reference documentation
on {spring-data-geode-docs-html}/#bootstrap-annotation-config[annotation-based configuration]. For a quick reference on {spring-data-geode-docs-html}/#bootstrap-annotation-config[annotation-based configuration]. For a quick reference
or an overview of Annotation-based Configuration, see the {spring-data-geode-docs-html}/#bootstap-annotations-quickstart[annotations quickstart]. and overview of annotation-based configuration, see the
{spring-data-geode-docs-html}/#bootstap-annotations-quickstart[annotations quickstart].
TIP: See the corresponding sample link:guides/boot-configuration.html[guide] and {github-samples-url}/boot/configuration[code] TIP: See the corresponding sample link:guides/boot-configuration.html[guide] and {github-samples-url}/boot/configuration[code]
to see Spring Boot auto-configuration for {geode-name} in action. to see Spring Boot auto-configuration for {geode-name} in action.
[[geode-configuration-auto-customizing]] [[geode-configuration-auto-customizing]]
=== Customizing Auto-configuration === Customizing Auto-configuration
You might ask "`how I can customize the Auto-configuration provided by SBDG if I do not explicitly declare You might ask, "`How do I customize the auto-configuration provided by SBDG if I do not explicitly declare
the annotation?`" the annotation?`"
For example, you may want to customize the member's `name`. You know that the For example, you may want to customize the member's name. You know that the
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html[`@ClientCacheApplication`] annotation {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html[`@ClientCacheApplication`] annotation
provides the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableGemFireProperties.html#name--[`name`] attribute provides the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableGemFireProperties.html#name--[`name`] attribute
so that you can set the client member's `name`. However, SBDG has already implicitly declared the `@ClientCacheApplication` so that you can set the client member's name. However, SBDG has already implicitly declared the `@ClientCacheApplication`
annotation throgh auto-configuration on your behalf. What do you do? annotation through auto-configuration on your behalf. What do you do?
In this case, SBDG supplies a few useful annotations. In this case, SBDG supplies a few additional annotations.
For example, to set the (client or peer) member's `name`, you can use the `@UseMemberName` annotation: For example, to set the (client or peer) member's name, you can use the `@UseMemberName` annotation:
.Setting the member's name using `@UseMemberName` .Setting the member's name using `@UseMemberName`
==== ====
@@ -55,8 +55,8 @@ For example, to set the (client or peer) member's `name`, you can use the `@UseM
---- ----
@SpringBootApplication @SpringBootApplication
@UseMemberName("MyMemberName") @UseMemberName("MyMemberName")
class SpringBootClientCacheApplication { class SpringBootApacheGeodeClientCacheApplication {
///... //...
} }
---- ----
==== ====
@@ -84,11 +84,14 @@ spring.data.gemfire.cache.name = MyMemberName
---- ----
==== ====
NOTE: The `spring.data.gemfire.cache.name` property is an alias for the `spring.data.gemfire.name` property. Both
properties do the same thing (set the name of the client or peer member node).
In general, there are three ways to customize configuration, even in the context of SBDG's auto-configuration: In general, there are three ways to customize configuration, even in the context of SBDG's auto-configuration:
* Using the {spring-boot-data-geode-javadoc}/org/springframework/geode/config/annotation/package-summary.html[annotations] * Using {spring-boot-data-geode-javadoc}/org/springframework/geode/config/annotation/package-summary.html[annotations]
provided by SBDG for common and popular concerns (such as naming client or peer members with `@UseMemberName` or enabling provided by SBDG for common and popular concerns (such as naming client or peer members with the `@UseMemberName`
durable clients with `@EnableDurableClient`). annotation or enabling durable clients with the `@EnableDurableClient` annotation).
* Using well-known and documented {spring-data-geode-docs-html}/#bootstrap-annotation-config-properties[properties] * Using well-known and documented {spring-data-geode-docs-html}/#bootstrap-annotation-config-properties[properties]
(such as `spring.application.name`, or `spring.data.gemfire.name`, or `spring.data.gemfire.cache.name`). (such as `spring.application.name`, or `spring.data.gemfire.name`, or `spring.data.gemfire.cache.name`).
@@ -101,12 +104,13 @@ TIP: For the complete list of documented properties, see <<geode-configuration-m
[[geode-configuration-auto-disabling]] [[geode-configuration-auto-disabling]]
=== Disabling Auto-configuration === Disabling Auto-configuration
Spring Boot's Reference documentation explains how to disable {spring-boot-docs-html}/#using-boot-disabling-specific-auto-configuration[disable Spring Boot auto-configuration]. Spring Boot's reference documentation explains how to
{spring-boot-docs-html}/#using-boot-disabling-specific-auto-configuration[disable Spring Boot auto-configuration].
<<geode-auto-configuration-disable>> also explains how to disable SBDG auto-confiugration. <<geode-auto-configuration-disable>> also explains how to disable SBDG auto-configuration.
In a nutshell, if you want to disable any auto-configuration provided by either Spring Boot or SBDG, In a nutshell, if you want to disable any auto-configuration provided by either Spring Boot or SBDG, declare your intent
declare your intent in the `@SpringBootApplication` annotation: in the `@SpringBootApplication` annotation:
.Disabling Specific Auto-configuration Classes .Disabling Specific Auto-configuration Classes
==== ====
@@ -115,7 +119,7 @@ declare your intent in the `@SpringBootApplication` annotation:
@SpringBootApplication( @SpringBootApplication(
exclude = { DataSourceAutoConfiguration.class, PdxAutoConfiguration.class } exclude = { DataSourceAutoConfiguration.class, PdxAutoConfiguration.class }
) )
class SpringBootClientCacheApplication { class SpringBootApacheGeodeClientCacheApplication {
// ... // ...
} }
---- ----
@@ -128,10 +132,11 @@ CAUTION: Make sure you understand what you are doing when you disable auto-confi
<<geode-autoconfiguration-annotations-overriding>> explains how to override SBDG auto-configuration. <<geode-autoconfiguration-annotations-overriding>> explains how to override SBDG auto-configuration.
In a nutshell, if you want to override the default auto-configuration provided by SBDG, you must annotate In a nutshell, if you want to override the default auto-configuration provided by SBDG, you must annotate your
your `@SpringBootApplication` class with your intent. `@SpringBootApplication` class with your intent.
For example, suppose you want to configure and bootstrap an {geode-name} `CacheServer` application (a peer, not a client): For example, suppose you want to configure and bootstrap an {geode-name} `CacheServer` application
(a peer, not a client):
.Overriding the default `ClientCache` _Auto-Configuration_ by configuring & bootstrapping a `CacheServer` application .Overriding the default `ClientCache` _Auto-Configuration_ by configuring & bootstrapping a `CacheServer` application
==== ====
@@ -139,7 +144,7 @@ For example, suppose you want to configure and bootstrap an {geode-name} `CacheS
---- ----
@SpringBootApplication @SpringBootApplication
@CacheServerApplication @CacheServerApplication
class SpringBootCacheServerApplication { class SpringBootApacheGeodeCacheServerApplication {
// ... // ...
} }
---- ----
@@ -153,14 +158,16 @@ You can also explicitly declare the `@ClientCacheApplication` annotation on your
---- ----
@SpringBootApplication @SpringBootApplication
@ClientCacheApplication @ClientCacheApplication
class SpringBootClientCacheApplication { class SpringBootApacheGeodeClientCacheApplication {
// ... // ...
} }
---- ----
==== ====
You are overriding SBDG's auto-configuration of the `ClientCache` instance. As a result, you have now also implicitly You are overriding SBDG's auto-configuration of the `ClientCache` instance. As a result, you have now also implicitly
consented to being responsible for other aspects of the configuration (such as security). Why does that happen? consented to being responsible for other aspects of the configuration (such as security).
Why does that happen?
It happens because, in certain cases, such as security, certain aspects of security configuration (such as SSL) must be It happens because, in certain cases, such as security, certain aspects of security configuration (such as SSL) must be
configured before the cache instance is created. Also, Spring Boot always applies user configuration before configured before the cache instance is created. Also, Spring Boot always applies user configuration before
@@ -171,30 +178,31 @@ CAUTION: Make sure you understand what you are doing when you override auto-conf
[[geode-configuration-auto-replacing]] [[geode-configuration-auto-replacing]]
=== Replacing Auto-configuration === Replacing Auto-configuration
See the Spring Boot Reference guide on {spring-boot-docs-html}/#using-boot-replacing-auto-configuration[replacing auto-configuration]. See the Spring Boot reference documentation on
{spring-boot-docs-html}/#using-boot-replacing-auto-configuration[replacing auto-configuration].
[[geode-configuration-auto-explained]] [[geode-configuration-auto-explained]]
=== Understanding Auto-configuration === Understanding Auto-configuration
This section covers the SBDG provided auto-configuration classes that corresponding the SDG annotations in more detail. This section covers the SBDG provided auto-configuration classes that correspond to the SDG annotations in more detail.
To review the complete list of SBDG auto-confiugration classes, see <<geode-auto-configuration-disable-classes>>. To review the complete list of SBDG auto-confiugration classes, see <<geode-auto-configuration-disable-classes>>.
[[geode-configuration-declarative-auto-configuration-clientcacheapplication]] [[geode-configuration-declarative-auto-configuration-clientcacheapplication]]
==== `@ClientCacheApplication` ==== `@ClientCacheApplication`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/ClientCacheAutoConfiguration.html[`ClientCacheAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/ClientCacheAutoConfiguration.html[`ClientCacheAutoConfiguration`] class
corresponds to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html[`@ClientCacheApplication`] annotation. corresponds to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html[`@ClientCacheApplication`] annotation.
As explained in <<getting-started>> SBDG starts with the opinion that application developers primarily build {geode-name} As explained in <<getting-started>> SBDG starts with the opinion that application developers primarily build {geode-name}
<<geode-clientcache-applications,client applications>> by using Spring Boot. <<geode-clientcache-applications,client applications>> by using Spring Boot.
Technically, this means building Spring Boot applications with an {geode-name} `ClientCache` instance connected to a Technically, this means building Spring Boot applications with an {geode-name} `ClientCache` instance connected to
dedicated cluster of {geode-name} servers that manage the data as part of a a dedicated cluster of {geode-name} servers that manage the data as part of a
{apache-geode-docs}/topologies_and_comm/cs_configuration/chapter_overview.html[client/server] topology. {apache-geode-docs}/topologies_and_comm/cs_configuration/chapter_overview.html[client/server] topology.
By way of example, this means you that need not explicitly declare and annotate your `@SpringBootApplication` class By way of example, this means that you need not explicitly declare and annotate your `@SpringBootApplication` class
with SDG's `@ClientCacheApplication` annotation, as the following negative example shows: with SDG's `@ClientCacheApplication` annotation, as the following example shows:
.Do Not Do This .Do Not Do This
==== ====
@@ -202,27 +210,27 @@ with SDG's `@ClientCacheApplication` annotation, as the following negative examp
---- ----
@SpringBootApplication @SpringBootApplication
@ClientCacheApplication @ClientCacheApplication
class SpringBootClientCacheApplication { class SpringBootApacheGeodeClientCacheApplication {
// ... // ...
} }
---- ----
==== ====
SBDG's provided _Auto-configuration_ class is already meta-annotated with SDG's SBDG's provided auto-configuration class is already meta-annotated with SDG's `@ClientCacheApplication` annotation.
`@ClientCacheApplication` annotation. Therefore, you need only: Therefore, you need only do:
.Do This .Do This
==== ====
[source,java] [source,java]
---- ----
@SpringBootApplication @SpringBootApplication
class SpringBootClientCacheApplication { class SpringBootApacheGeodeClientCacheApplication {
// ... // ...
} }
---- ----
==== ====
TIP: See SDG's Reference Documentation for more details on {geode-name} TIP: See SDG's reference documentation for more details on {geode-name}
{spring-data-geode-docs-html}/#bootstrap-annotation-config-geode-applications[cache applications] {spring-data-geode-docs-html}/#bootstrap-annotation-config-geode-applications[cache applications]
and {spring-data-geode-docs-html}/#bootstrap-annotation-config-client-server-applications[client/server applications] and {spring-data-geode-docs-html}/#bootstrap-annotation-config-client-server-applications[client/server applications]
in particular. in particular.
@@ -230,11 +238,11 @@ in particular.
[[geode-configuration-declarative-auto-configuration-enablecaching]] [[geode-configuration-declarative-auto-configuration-enablecaching]]
==== `@EnableGemfireCaching` ==== `@EnableGemfireCaching`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/CachingProviderAutoConfiguration.html[`CachingProviderAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/CachingProviderAutoConfiguration.html[`CachingProviderAutoConfiguration`] class
corresponds to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/cache/config/EnableGemfireCaching.html[`@EnableGemfireCaching`] annotation. corresponds to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/cache/config/EnableGemfireCaching.html[`@EnableGemfireCaching`] annotation.
If you used the core Spring Framework to configure {geode-name} as a caching provider If you used the core Spring Framework to configure {geode-name} as a caching provider in
in {spring-framework-docs}/integration.html#cache[Spring's cache abstraction], you need to: {spring-framework-docs}/integration.html#cache[Spring's Cache Abstraction], you need to:
.Configuring caching using the Spring Framework .Configuring caching using the Spring Framework
==== ====
@@ -244,22 +252,23 @@ in {spring-framework-docs}/integration.html#cache[Spring's cache abstraction], y
@EnableCaching @EnableCaching
class CachingUsingApacheGeodeConfiguration { class CachingUsingApacheGeodeConfiguration {
@Bean @Bean
GemfireCacheManager cacheManager(GemFireCache cache) { GemfireCacheManager cacheManager(GemFireCache cache) {
GemfireCacheManager cacheManager = new GemfireCacheManager(); GemfireCacheManager cacheManager = new GemfireCacheManager();
cacheManager.setCache(cache); cacheManager.setCache(cache);
return cacheManager; return cacheManager;
} }
} }
---- ----
==== ====
If you use Spring Data for {geode-name}'s `@EnableGemfireCaching` annotation, you can simplify the preceding configuration: If you use Spring Data for {geode-name}'s `@EnableGemfireCaching` annotation, you can simplify the preceding
configuration:
.Configuring caching using Spring Data Geode .Configuring caching using Spring Data for {geode-name}
==== ====
[source,java] [source,java]
---- ----
@@ -273,7 +282,7 @@ class CachingUsingApacheGeodeConfiguration {
Also, if you use SBDG, you need only do: Also, if you use SBDG, you need only do:
.Configuring caching using Spring Data Geode .Configuring caching using Spring Boot for {geode-name}
==== ====
[source,java] [source,java]
---- ----
@@ -284,8 +293,8 @@ class CachingUsingApacheGeodeConfiguration {
---- ----
==== ====
This lets you focus on the areas in your application that would benefit from caching without having to enable This lets you focus on the areas in your application that would benefit from caching without having to enable the
the plumbing. You can then demarcate the service methods in your application that are good candidates for caching: plumbing. You can then demarcate the service methods in your application that are good candidates for caching:
.Using caching in your application .Using caching in your application
==== ====
@@ -294,27 +303,27 @@ the plumbing. You can then demarcate the service methods in your application tha
@Service @Service
class CustomerService { class CustomerService {
@Caching("CustomersByName") @Caching("CustomersByName")
Customer findBy(String name) { Customer findBy(String name) {
// ... // ...
} }
} }
---- ----
==== ====
TIP: See <<geode-caching-provider,documentation>> for more details. TIP: See <<geode-caching-provider,documentation on caching>> for more details.
[[geode-configuration-declarative-auto-configuration-enableautocontinuousqueies]] [[geode-configuration-declarative-auto-configuration-enableautocontinuousqueies]]
==== `@EnableContinuousQueries` ==== `@EnableContinuousQueries`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/ContinuousQueryAutoConfiguration.html[`ContinuousQueryAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/ContinuousQueryAutoConfiguration.html[`ContinuousQueryAutoConfiguration`] class
corresponds to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableContinuousQueries.html[`@EnableContinuousQueries`] annotation. corresponds to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableContinuousQueries.html[`@EnableContinuousQueries`] annotation.
Without having to enable anything, you can annotate your application (POJO) component method(s) with the SDG Without having to enable anything, you can annotate your application (POJO) component method(s) with the SDG
{spring-data-geode-javadoc}/org/springframework/data/gemfire/listener/annotation/ContinuousQuery.html[`@ContinuousQuery`] {spring-data-geode-javadoc}/org/springframework/data/gemfire/listener/annotation/ContinuousQuery.html[`@ContinuousQuery`]
annotation to register a CQ and start receiving events. The method acts as a `CqEvent` handler or, in {geode-name}'s annotation to register a CQ and start receiving events. The method acts as a `CqEvent` handler or, in {geode-name}'s
case, the method is an implementation of terminology, the method is an implementation of the
{apache-geode-javadoc}/org/apache/geode/cache/query/CqListener.html[`CqListener`]. {apache-geode-javadoc}/org/apache/geode/cache/query/CqListener.html[`CqListener`] interface.
.Declare application CQs .Declare application CQs
==== ====
@@ -323,32 +332,33 @@ case, the method is an implementation of
@Component @Component
class MyCustomerApplicationContinuousQueries { class MyCustomerApplicationContinuousQueries {
@ContinuousQuery("SELECT customer.* FROM /Customers customers" @ContinuousQuery("SELECT customer.* "
+ " WHERE customer.getSentiment().name().equalsIgnoreCase('UNHAPPY')") + " FROM /Customers customers"
public void handleUnhappyCustomers(CqEvent event) { + " WHERE customer.getSentiment().name().equalsIgnoreCase('UNHAPPY')")
// ... public void handleUnhappyCustomers(CqEvent event) {
} // ...
}
} }
---- ----
==== ====
As the preceding listing shows, you can define the events you are interested in receiving by using an OQL query with a finely tuned query As the preceding example shows, you can define the events you are interested in receiving by using an OQL query with a
predicate that describes the events of interests and implements the handler method to process the events (such as applying a credit finely tuned query predicate that describes the events of interests and implements the handler method to process the
to the customer's account and following up in email). events (such as applying a credit to the customer's account and following up in email).
TIP: See <<geode-continuous-query>> for more details. TIP: See <<geode-continuous-query>> for more details.
[[geode-configuration-declarative-auto-configuration-enablefunctions]] [[geode-configuration-declarative-auto-configuration-enablefunctions]]
==== `@EnableGemfireFunctionExecutions` & `@EnableGemfireFunctions` ==== `@EnableGemfireFunctionExecutions` & `@EnableGemfireFunctions`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/FunctionExecutionAutoConfiguration.html[`FunctionExecutionAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/FunctionExecutionAutoConfiguration.html[`FunctionExecutionAutoConfiguration`] class
corresponds to both the {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/config/EnableGemfireFunctionExecutions.html[`@EnableGemfireFunctionExecutions`] corresponds to both the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/config/EnableGemfireFunctionExecutions.html[`@EnableGemfireFunctionExecutions`]
and {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/config/EnableGemfireFunctions.html[`@EnableGemfireFunctions`] annotations. and SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/config/EnableGemfireFunctions.html[`@EnableGemfireFunctions`] annotations.
Whether you need to {spring-data-geode-docs-html}/#function-execution[execute] Whether you need to {spring-data-geode-docs-html}/#function-execution[execute]
or {spring-data-geode-docs-html}/#function-implementation[implement] a `Function`, SBDG detects the function or {spring-data-geode-docs-html}/#function-implementation[implement] a `Function`, SBDG detects the Function definition
definition and auto-configures it appropriately for use in your Spring Boot application. You need only define and auto-configures it appropriately for use in your Spring Boot application. You need only define the Function
the function execution or implementation in a package below the main `@SpringBootApplication` class: execution or implementation in a package below the main `@SpringBootApplication` class:
.Declare a Function Execution .Declare a Function Execution
==== ====
@@ -377,7 +387,7 @@ package example.app.service;
class CustomerService { class CustomerService {
@Autowired @Autowired
private MyCustomerapplicationFunctions customerFunctions; private MyCustomerApplicationFunctions customerFunctions;
void analyzeCustomerSentiment(Customer customer) { void analyzeCustomerSentiment(Customer customer) {
@@ -391,11 +401,11 @@ class CustomerService {
---- ----
==== ====
The same pattern basically applies to function implementations, except in the implementation case, in which SBDG "`registers`" The same pattern basically applies to Function implementations, except in the implementation case, SBDG registers
the function implementation for use (that is, to be called by a function execution). the Function implementation for use (that is, to be called by a Function execution).
Doing so lets you focus on defining the logic required by your application and not worry about Doing so lets you focus on defining the logic required by your application and not worry about how Functions
how functions are registered, called, and so on. SBDG handles this concern for you. are registered, called, and so on. SBDG handles this concern for you.
NOTE: Function implementations are typically defined and registered on the server-side. NOTE: Function implementations are typically defined and registered on the server-side.
@@ -404,12 +414,12 @@ TIP: See <<geode-functions>> for more details.
[[geode-configuration-declarative-auto-configuration-enablerepositories]] [[geode-configuration-declarative-auto-configuration-enablerepositories]]
==== `@EnableGemfireRepositories` ==== `@EnableGemfireRepositories`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/GemFireRepositoriesAutoConfigurationRegistrar.html[`GemFireRepositoriesAutoConfigurationRegistrar`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/GemFireRepositoriesAutoConfigurationRegistrar.html[`GemFireRepositoriesAutoConfigurationRegistrar`] class
corresponds to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/repository/config/EnableGemfireRepositories.html[`@EnableGemfireRepositories`] annotation. corresponds to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/repository/config/EnableGemfireRepositories.html[`@EnableGemfireRepositories`] annotation.
As with functions, you need concern yourself only with the data access operations (such as basic CRUD and simple queries) required by As with Functions, you need concern yourself only with the data access operations (such as basic CRUD and simple queries)
your application to carry out its functions, not with how to create and perform them (for example, `Region.get(key)` required by your application to carry out its operation, not with how to create and perform them (for example,
and `Region.put(key, obj)`) or execute them (for example, `Query.execute(arguments)`). `Region.get(key)` and `Region.put(key, obj)`) or execute them (for example, `Query.execute(arguments)`).
Start by defining your Spring Data Repository: Start by defining your Spring Data Repository:
@@ -421,13 +431,13 @@ package example.app.repo;
interface CustomerRepository extends CrudRepository<Customer, Long> { interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findBySentimentEqualTo(Sentiment sentiment); List<Customer> findBySentimentEqualTo(Sentiment sentiment);
} }
---- ----
==== ====
Then you can use it: Then you can inject the Repository into an application component and use it:
.Using the application-specific Repository .Using the application-specific Repository
==== ====
@@ -438,21 +448,22 @@ package example.app.sevice;
@Service @Service
class CustomerService { class CustomerService {
@Autowired @Autowired
private CustomerRepository repository; private CustomerRepository repository;
public void processCustomersWithSentiment(Sentiment sentiment) { public void processCustomersWithSentiment(Sentiment sentiment) {
this.repository.findBySentimentEqualTo(sentiment).forEach(customer -> { /* ... */ }); this.repository.findBySentimentEqualTo(sentiment)
.forEach(customer -> { /* ... */ });
// ... // ...
} }
} }
---- ----
==== ====
Your application-specific repository simply needs to be declared in a package below the main `@SpringBootApplication` Your application-specific Repository simply needs to be declared in a package below the main `@SpringBootApplication`
class. Again, you are focusing only on the data access operations and queries required to carry out the functions class. Again, you are focusing only on the data access operations and queries required to carry out the operatinons
of your application, nothing more. of your application, nothing more.
TIP: See <<geode-repositories>> for more details. TIP: See <<geode-repositories>> for more details.
@@ -460,15 +471,13 @@ TIP: See <<geode-repositories>> for more details.
[[geode-configuration-declarative-auto-configuration-enablelogging]] [[geode-configuration-declarative-auto-configuration-enablelogging]]
==== `@EnableLogging` ==== `@EnableLogging`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/LoggingAutoConfiguration.html[`LoggingAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/LoggingAutoConfiguration.html[`LoggingAutoConfiguration`] class
corresponds to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLogging.html[`@EnableLogging`] annotation. corresponds to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLogging.html[`@EnableLogging`] annotation.
Logging is an essential application concern to understand what is happening in the system along with when and where Logging is an essential application concern to understand what is happening in the system along with when and where
the events occurred. By default, SBDG auto-configures logging for {geode-name} with the default log-level, the events occurred. By default, SBDG auto-configures logging for {geode-name} with the default log-level, "`config`".
`config`.
You can change an aspect of logging, such as the log-level, in Spring Boot You can change any aspect of logging, such as the log-level, in Spring Boot `application.properties`:
`application.properties`:
.Change the log-level for {geode-name} .Change the log-level for {geode-name}
==== ====
@@ -480,31 +489,33 @@ spring.data.gemfire.cache.log-level=debug
---- ----
==== ====
You can also configure other aspects, such as the log file size and disk space limits for the file system location NOTE: The 'spring.data.gemfire.logging.level' property is an alias for `spring.data.gemfire.cache.log-level`.
used to store the {geode-name} log files at runtime.
You can also configure other aspects, such as the log file size and disk space limits for the filesystem location used
to store the {geode-name} log files at runtime.
Under the hood, {geode-name}'s logging is based on Log4j. Therefore, you can configure {geode-name} logging to use any Under the hood, {geode-name}'s logging is based on Log4j. Therefore, you can configure {geode-name} logging to use any
logging provider (such as Logback) and configuration metadata appropriate for that logging provider so long as you supply logging provider (such as Logback) and configuration metadata appropriate for that logging provider so long as you
the necessary adapter between Log4j and whatever logging system you use. For instance, if you include supply the necessary adapter between Log4j and whatever logging system you use. For instance, if you include
`org.springframework.boot:spring-boot-starter-logging`, you are using Logback and you need the `org.springframework.boot:spring-boot-starter-logging`, you are using Logback and you will need the
`org.apache.logging.log4j:log4j-to-slf4j` adapter. `org.apache.logging.log4j:log4j-to-slf4j` adapter.
[[geode-configuration-declarative-auto-configuration-enablepdx]] [[geode-configuration-declarative-auto-configuration-enablepdx]]
==== `@EnablePdx` ==== `@EnablePdx`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/PdxSerializationAutoConfiguration.html[`PdxSerializationAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/PdxSerializationAutoConfiguration.html[`PdxSerializationAutoConfiguration`] class
corresponds to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html[`@EnablePdx`] annotation. corresponds to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html[`@EnablePdx`] annotation.
Any time you need to send an object over the network or overflow or persist an object to disk, your application domain Any time you need to send an object over the network or overflow or persist an object to disk, your application domain
object must be serializable. It would be painful to have to implement `java.io.Serializable` in every one of your model object must be serializable. It would be painful to have to implement `java.io.Serializable` in every one of your
application domain objects (such as `Customer`) that would potentially need to be serialized. application domain model objects (such as `Customer`) that would potentially need to be serialized.
Furthermore, using Java serialization may not be ideal (it may not be the most portable or efficient solution) in all cases Furthermore, using Java Serialization may not be ideal (it may not be the most portable or efficient solution) in all
or even possible in other cases (such as when you use a third party library over which you have no control). cases or even possible in other cases (such as when you use a third party library over which you have no control).
In these situations, you need to be able to send your object anywhere without unduly requiring the class type In these situations, you need to be able to send your object anywhere, anytime without unduly requiring the class type
to be serializable and exist on the classpath for every place it is sent. Indeed, the final destination to be serializable and exist on the classpath in every place it is sent. Indeed, the final destination may not even be
may not even be a Java application. This is where {geode-name} a Java application. This is where {geode-name}
{apache-geode-docs}/developing/data_serialization/gemfire_pdx_serialization.html[PDX Serialization] steps in to help. {apache-geode-docs}/developing/data_serialization/gemfire_pdx_serialization.html[PDX Serialization] steps in to help.
However, you need not figure out how to configure PDX to identify the application class types that needs to be However, you need not figure out how to configure PDX to identify the application class types that needs to be
@@ -517,13 +528,13 @@ serialized. Instead, you can define your class type as follows:
@Region("Customers") @Region("Customers")
class Customer { class Customer {
@Id @Id
private Long id; private Long id;
@Indexed @Indexed
private String name; private String name;
// ... // ...
} }
---- ----
==== ====
@@ -535,10 +546,11 @@ TIP: See <<geode-data-serialization>> for more details.
[[geode-configuration-declarative-auto-configuration-enablesecurity]] [[geode-configuration-declarative-auto-configuration-enablesecurity]]
==== `@EnableSecurity` ==== `@EnableSecurity`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/ClientSecurityAutoConfiguration.html[`ClientSecurityAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/ClientSecurityAutoConfiguration.html[`ClientSecurityAutoConfiguration`] class
and {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/PeerSecurityAutoConfiguration.html[`PeerSecurityAutoConfiguration`] class and {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/PeerSecurityAutoConfiguration.html[`PeerSecurityAutoConfiguration`] class
correspond to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html[`@EnableSecurity`] annotation, but they apply correspond to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html[`@EnableSecurity`] annotation,
Security (specifically, Authentication and Authorization configuration) for both clients and servers. but they apply security (specifically, authentication and authorization (auth) configuration) for both clients
and servers.
Configuring your Spring Boot, {geode-name} `ClientCache` application to properly authenticate with a cluster of secure Configuring your Spring Boot, {geode-name} `ClientCache` application to properly authenticate with a cluster of secure
{geode-name} servers is as simple as setting a username and a password in Spring Boot `application.properties`: {geode-name} servers is as simple as setting a username and a password in Spring Boot `application.properties`:
@@ -554,41 +566,42 @@ spring.data.gemfire.security.password=r0b!n5ucks
---- ----
==== ====
NOTE: Authentication is even easier to configure in a managed environment, such as PCF when using PCC. NOTE: Authentication is even easier to configure in a managed environment, such as PCF when using PCC. You need not do
You need not do anything. anything.
Authorization is configured on the server-side and is made simple with SBDG and the help of https://shiro.apache.org/[Apache Shiro]. Authorization is configured on the server-side and is made simple with SBDG and the help of
Of course, this assumes you use SBDG to configure and bootstrap your {geode-name} cluster in the first place, https://shiro.apache.org/[Apache Shiro].
which is even easier with SBDG. See <<geode-cluster-configuration-bootstrapping>>. Of course, this assumes you use SBDG to configure and bootstrap your {geode-name} cluster in the first place, which is
even easier with SBDG. See <<geode-cluster-configuration-bootstrapping>>.
TIP: See <<geode-security>> for more details. TIP: See <<geode-security>> for more details.
[[geode-configuration-declarative-auto-configuration-enablessl]] [[geode-configuration-declarative-auto-configuration-enablessl]]
==== `@EnableSsl` ==== `@EnableSsl`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/SslAutoConfiguration.html[`SslAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/SslAutoConfiguration.html[`SslAutoConfiguration`] class
corresponds to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html[`@EnableSsl`] annotation. corresponds to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html[`@EnableSsl`] annotation.
Configuring SSL for secure transport (TLS) between your Spring Boot, {geode-name} `ClientCache` application and the Configuring SSL for secure transport (TLS) between your Spring Boot, {geode-name} `ClientCache` application and an
cluster can be a real problem, especially to get correct from the start. So, it is something that SBDG makes {geode-name} cluster can be a real problem, especially to get right from the start. So, it is something that SBDG
as simple as possible. makes as simple as possible.
You can supply a `trusted.keystore` file containing the certificates in a well-known location (such as the root of your You can supply a `trusted.keystore` file containing the certificates in a well-known location (such as the root of your
application classpath), and SBDG's auto-configuration kicks in and handle of the rest. application classpath), and SBDG's auto-configuration steps in to handle the rest.
This is useful during development, but we highly recommend using a more secure procedure (such as integrating with a This is useful during development, but we highly recommend using a more secure procedure (such as integrating with a
secure credential store like LDAP, CredHub, or Vault) when deploying your Spring Boot application to production. secure credential store like LDAP, CredHub or Vault) when deploying your Spring Boot application to production.
TIP: See <<geode-security-ssl,documentation>> for more details. TIP: See <<geode-security-ssl>> for more details.
[[geode-configuration-declarative-auto-configuration-enablespringsession]] [[geode-configuration-declarative-auto-configuration-enablespringsession]]
==== `@EnableGemFireHttpSession` ==== `@EnableGemFireHttpSession`
NOTE: The {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/SpringSessionAutoConfiguration.html[`SpringSessionAutoConfiguration`] class NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/SpringSessionAutoConfiguration.html[`SpringSessionAutoConfiguration`] class
corresponds to the {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/EnableSsl.html[`@EnableSsl`] annotation. corresponds to the SSDG {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/EnableGemFireHttpSession.html[`@EnableGemFireHttpSession`] annotation.
Configuring {geode-name} to serve as the (HTTP) Session state caching provider by using Spring Session requires only Configuring {geode-name} to serve as the (HTTP) session state caching provider by using Spring Session requires that
that you include the correct starter, such as `spring-geode-starter-session`: you only include the correct starter, that is `spring-geode-starter-session`:
.Using Spring Session .Using Spring Session
==== ====
@@ -603,9 +616,8 @@ that you include the correct starter, such as `spring-geode-starter-session`:
==== ====
With Spring Session -- and specifically Spring Session for {geode-name} (SSDG) -- on the classpath of your Spring Boot, With Spring Session -- and specifically Spring Session for {geode-name} (SSDG) -- on the classpath of your Spring Boot,
{geode-name} `ClientCache` Web application, you can manage your (HTTP) Session state with {geode-name}. No further {geode-name} `ClientCache` Web application, you can manage your (HTTP) session state with {geode-name}. No further
configuration is needed. SBDG auto-configuration detects Spring Session on the application classpath and does configuration is needed. SBDG auto-configuration detects Spring Session on the application classpath and does the rest.
the right thing.
TIP: See <<geode-session>> for more details. TIP: See <<geode-session>> for more details.
@@ -613,10 +625,10 @@ TIP: See <<geode-session>> for more details.
==== RegionTemplateAutoConfiguration ==== RegionTemplateAutoConfiguration
The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/RegionTemplateAutoConfiguration.html[`RegionTemplateAutoConfiguration`] class The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/RegionTemplateAutoConfiguration.html[`RegionTemplateAutoConfiguration`] class
has no corresponding SDG annotation. However, the auto-configuration of a `GemfireTemplate` for every single has no corresponding SDG annotation. However, the auto-configuration of a `GemfireTemplate` for every {geode-name}
{geode-name} `Region` defined and declared in your Spring Boot application is still supplied by SBDG. `Region` defined and declared in your Spring Boot application is still supplied by SBDG.
For example, you can define a region by using: For example, you can define a Region by using:
.Region definition using JavaConfig .Region definition using JavaConfig
==== ====
@@ -625,23 +637,22 @@ For example, you can define a region by using:
@Configuration @Configuration
class GeodeConfiguration { class GeodeConfiguration {
@Bean("Customers")
ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) {
@Bean("Customers") ClientRegionFactoryBean<Long, Customer> customersRegion =
ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) { new ClientRegionFactoryBean<>();
ClientRegionFactoryBean<Long, Customer> customersRegion = customersRegion.setCache(cache);
new ClientRegionFactoryBean<>(); customersRegion.setShortcut(ClientRegionShortcut.PROXY);
customersRegion.setCache(cache); return customersRegion;
customersRegion.setShortcut(ClientRegionShortcut.PROXY); }
return customersRegion;
}
} }
---- ----
==== ====
Alternatively, you can define the `Customers` region by using `@EnableEntityDefinedRegions`: Alternatively, you can define the `Customers` Region by using `@EnableEntityDefinedRegions`:
.Region definition using `@EnableEntityDefinedRegions` .Region definition using `@EnableEntityDefinedRegions`
==== ====
@@ -656,7 +667,7 @@ class GeodeConfiguration {
==== ====
Then SBDG supplies a `GemfireTemplate` instance that you can use to perform low-level data-access operations Then SBDG supplies a `GemfireTemplate` instance that you can use to perform low-level data-access operations
(indirectly) on the `Customers` region: (indirectly) on the `Customers` Region:
.Use the `GemfireTemplate` to access the "Customers" Region .Use the `GemfireTemplate` to access the "Customers" Region
==== ====
@@ -665,21 +676,21 @@ Then SBDG supplies a `GemfireTemplate` instance that you can use to perform low-
@Repository @Repository
class CustomersDao { class CustomersDao {
@Autowired @Autowired
@Qualifier("customersTemplate") @Qualifier("customersTemplate")
private GemfireTemplate customersTemplate; private GemfireTemplate customersTemplate;
Customer findById(Long id) { Customer findById(Long id) {
return this.customerTemplate.get(id); return this.customerTemplate.get(id);
} }
} }
---- ----
==== ====
You need not explicitly configure `GemfireTemplates` for each region to which you need low-level data access You need not explicitly configure `GemfireTemplates` for each Region to which you need low-level data access (such as
(such as when you are not using the Spring Data Repository abstraction). when you are not using the Spring Data Repository abstraction).
Be careful to "`qualify`" the `GemfireTemplate` for the region to which you need data access, especially given that you Be careful to qualify the `GemfireTemplate` for the Region to which you need data access, especially given that you
probably have more than one Region defined in your Spring Boot application. probably have more than one Region defined in your Spring Boot application.
TIP: See <<geode-data-access-region-templates>> for more details. TIP: See <<geode-data-access-region-templates>> for more details.

View File

@@ -3,52 +3,53 @@
:geode-name: {apache-geode-name} :geode-name: {apache-geode-name}
The primary purpose of any software development framework is to help you be productive as quickly and as easily The primary purpose of any software development framework is to help you be productive as quickly and as easily as
as possible and to do so in a reliable manner. possible and to do so in a reliable manner.
As application developers, we want a framework to provide constructs that are both intuitive and familiar so that their As application developers, we want a framework to provide constructs that are both intuitive and familiar so that their
behaviors are predictable. This provided convenience not only helps you hit the ground running in the right behaviors are predictable. This provided convenience not only helps you hit the ground running in the right direction
direction sooner but increases your focus on the application domain so that you can better understand the problem sooner but increases your focus on the application domain so that you can better understand the problem you are trying
you are trying to solve in the first place. Once the problem domain is well understood, you are more apt to make to solve in the first place. Once the problem domain is well understood, you are more apt to make informed decisions
informed decisions about the design, which leads to better outcomes, faster. about the design, which leads to better outcomes, faster.
This is exactly what Spring Boot's auto-configuration provides for you. It enables features, services, and supporting This is exactly what Spring Boot's auto-configuration provides for you. It enables features, functionality, services
infrastructure for Spring applications in a loosely integrated way by using conventions (such as the classpath) that ultimately and supporting infrastructure for Spring applications in a loosely integrated way by using conventions (such as the
help you keep your attention and focus on solving the problem at hand and not on the plumbing. classpath) that ultimately help you keep your attention and focus on solving the problem at hand and not on the plumbing.
For example, if you are building a web application, you can include the `org.springframework.boot:spring-boot-starter-web` For example, if you are building a web application, you can include the `org.springframework.boot:spring-boot-starter-web`
dependency on your application classpath. Not only does Spring Boot enable you to build Spring Web MVC Controllers dependency on your application classpath. Not only does Spring Boot enable you to build Spring Web MVC Controllers
appropriate to your application UC (your responsibility), but it also bootstraps your web application in an embedded servlet appropriate to your application UC (your responsibility), but it also bootstraps your web application in an embedded
container on startup (Boot's responsibility). Servlet container on startup (Spring Boot's responsibility).
This saves you from having to handle many low-level, repetitive, and tedious development tasks that are highly error-prone This saves you from having to handle many low-level, repetitive, and tedious development tasks that are error-prone and
when you are trying to solve problems. You need not care how the plumbing works until you need to customize something. And, when you easy to get wrong when you are trying to solve problems. You need not care how the plumbing works until you need to
do, you are better informed and prepared to do so. customize something. And, when you do, you are better informed and prepared to do so.
It is also equally essential that frameworks, such as Spring Boot, get out of the way quickly when application requirements It is also equally essential that frameworks, such as Spring Boot, get out of the way quickly when application
diverge from the provided defaults. The is the beautiful and powerful thing about Spring Boot and why it is second requirements diverge from the provided defaults. This is the beautiful and powerful thing about Spring Boot and why
to none in its class. it is second to none in its class.
Still, auto-configuration does not solve every problem all the time. Therefore, you need to use declarative Still, auto-configuration does not solve every problem all the time. Therefore, you need to use declarative
configuration in some cases, whether expressed as bean definitions, in properties, or by some other means. This is so that configuration in some cases, whether expressed as bean definitions, in properties, or by some other means. This is so
frameworks do not leave things to chance, especially when they are ambiguous. The framework gives you a choice. that frameworks do not leave things to chance, especially when things are ambiguous. The framework gives you choice.
Keeping our goals in mind, this chapter: Keeping our goals in mind, this chapter:
* Refers you to the SDG annotations covered by SBDG's auto-configuration. * Refers you to the SDG annotations covered by SBDG's auto-configuration.
* lists all SDG annotations not covered by SBDG's auto-configuration. * Lists all SDG annotations not covered by SBDG's auto-configuration.
* Covers the SBDG, SSDG, and SDG annotations that you must explicitly declare and that provide the most value * Covers the SBDG, SSDG and SDG annotations that you must explicitly declare and that provide the most value
and productivity when getting started with {geode-name} in Spring [Boot] applications. and productivity when getting started with {geode-name} in Spring [Boot] applications.
NOTE: SDG refers to {spring-data-geode-website}[Spring Data for {geode-name}]. SSDG refers to NOTE: SDG refers to {spring-data-geode-website}[Spring Data for {geode-name}]. SSDG refers to
{spring-session-data-gemfire-website}[Spring Session for {geode-name}]. SBDG refers to {spring-session-data-gemfire-website}[Spring Session for {geode-name}]. SBDG refers to
Spring Boot for {geode-name} (this project). Spring Boot for {geode-name} (this project).
TIP: The list of SDG annotations covered by SBDG's auto-configuration is discussed in detail in the <<appendix,Appendix>>, TIP: The list of SDG annotations covered by SBDG's auto-configuration is discussed in detail in the <<appendix>>,
in the <<geode-auto-configuration-annotations,Auto-configuration vs. Annotation-based configuration>> section. in the <<geode-auto-configuration-annotations,Auto-configuration vs. Annotation-based configuration>> section.
To be absolutely clear about which SDG Annotations we are referring to, we mean the SDG annotations in the To be absolutely clear about which SDG annotations we are referring to, we mean the SDG annotations in the
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-summary.html[`org.springframework.data.gemfire.config.annotation`] package. {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-summary.html[`org.springframework.data.gemfire.config.annotation`]
package.
In subsequent sections, we also cover which annotations are added by SBDG. In subsequent sections, we also cover which annotations are added by SBDG.
@@ -88,9 +89,10 @@ The following SDG annotations are not implicitly applied by SBDG's auto-configur
* `@EnableStatistics` * `@EnableStatistics`
* `@UseGemFireProperties` * `@UseGemFireProperties`
(Note that this content was also covered in <<geode-autoconfiguration-annotations-explicit>>.) NOTE: This content was also covered in <<geode-autoconfiguration-annotations-explicit>>.
One reason for this is because several of the annotations are server-specific: One reason SBDG does not provide auto-configuration for several of the annotations is because the annotations
are server-specific:
* `@EnableCacheServer(s)` * `@EnableCacheServer(s)`
* `@EnableGatewayReceiver` * `@EnableGatewayReceiver`
@@ -107,12 +109,12 @@ instance.
Other annotations are driven by need, including: Other annotations are driven by need, including:
* `@EnableAutoRegionLookup` and `@EnableBeanFactoryLocator`: Really useful only when mixing configuration metadata * `@EnableAutoRegionLookup` and `@EnableBeanFactoryLocator`: Really useful only when mixing configuration metadata
formats, such as Spring config with {geode-name} `cache.xml`. This is usually the case only if you have legacy `cache.xml` formats, such as Spring config with {geode-name} `cache.xml`. This is usually the case only if you have legacy
config to begin with. Otherwise, you should not do this. `cache.xml` config to begin with. Otherwise, you should not use these annotations.
* `@EnableCompression`: Requires the Snappy Compression Library to be on your application classpath. * `@EnableCompression`: Requires the Snappy Compression Library to be on your application classpath.
* `@EnableDiskStore(s)` Used only for overflow and persistence. * `@EnableDiskStore(s)` Used only for overflow and persistence.
* `@EnableOffHeap`: Enables data to be stored in main memory, which is useful only when your application data * `@EnableOffHeap`: Enables data to be stored in main memory, which is useful only when your application data (that is,
(that is, objects stored in {geode-name}) are generally uniform in size. objects stored in {geode-name}) are generally uniform in size.
* `@EnableGemFireAsLastResource`: Needed only in the context of JTA Transactions. * `@EnableGemFireAsLastResource`: Needed only in the context of JTA Transactions.
* `@EnableStatistics`: Useful if you need runtime metrics. However, enabling statistics gathering does consume * `@EnableStatistics`: Useful if you need runtime metrics. However, enabling statistics gathering does consume
considerable system resources (CPU & Memory). considerable system resources (CPU & Memory).
@@ -123,20 +125,20 @@ Still other annotations require more careful planning:
* `@EnableExpiration` * `@EnableExpiration`
* `@EnableIndexing` * `@EnableIndexing`
One annotation is used exclusively for Unit Testing: One annotation is used exclusively for unit testing:
* `@EnableGemFireMockObjects` * `@EnableGemFireMockObjects`
The bottom-line is that a framework should not auto-configure every possible feature, especially when the features The bottom-line is that a framework should not auto-configure every possible feature, especially when the features
consume additional system resources or require more careful planning (as determined by the use case). consume additional system resources or require more careful planning (as determined by the use case).
Still, all of these annotations are available for the application developer to use when needed. However, all of these annotations are available for the application developer to use when needed.
[[geode-configuration-declarative-annotations-productivity]] [[geode-configuration-declarative-annotations-productivity]]
=== Productivity Annotations === Productivity Annotations
This section calls out the annotations we believe to be most beneficial for your application development purposes when This section calls out the annotations we believe to be most beneficial for your application development purposes when
using {geode-name} in Spring Boot applications. using {geode-name} in Spring [Boot] applications.
[[geode-configuration-declarative-annotations-productivity-enableclusteraware]] [[geode-configuration-declarative-annotations-productivity-enableclusteraware]]
==== `@EnableClusterAware` (SBDG) ==== `@EnableClusterAware` (SBDG)
@@ -153,33 +155,35 @@ class SpringBootApacheGeodeClientCacheApplication { }
---- ----
==== ====
When you annotate your main `@SpringBootApplication` class with `@EnableClusterAware`, When you annotate your main `@SpringBootApplication` class with `@EnableClusterAware`, your Spring Boot, {geode-name}
your Spring Boot, {geode-name} `ClientCache` application is able to seamlessly switch between client/server `ClientCache` application is able to seamlessly switch between client/server and local-only topologies with no code
and local-only topologies with no code or configuration changes, regardless of the runtime environment or configuration changes, regardless of the runtime environment (such as local/standalone versus cloud-managed
(such as local/standalone versus cloud-managed environments). environments).
When a cluster of {geode-name} servers is detected, the client application sends and receives data to and from the When a cluster of {geode-name} servers is detected, the client application sends and receives data to and from the
cluster. If a cluster is not available, the client automatically switches to storing data locally on the client {geode-name} cluster. If a cluster is not available, the client automatically switches to storing data locally on the
by using `LOCAL` Regions. client by using `LOCAL` Regions.
Additionally, the `@EnableClusterAware` annotation is meta-annotated with SDG's Additionally, the `@EnableClusterAware` annotation is meta-annotated with SDG's
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html[`@EnableClusterConfiguration`] annotation. {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html[`@EnableClusterConfiguration`]
annotation.
The `@EnableClusterConfiguration` annotation lets configuration metadata defined on the client (such as region and index The `@EnableClusterConfiguration` annotation lets configuration metadata defined on the client (such as Region and Index
definitions, as needed by the application based on requirements and use cases) be sent to the cluster of servers. definitions, as needed by the application based on requirements and use cases) be sent to the cluster of servers. If
If those schema objects are not already present, they are created by the servers in the cluster in such a way that those schema objects are not already present, they are created by the servers in the cluster in such a way that the
the servers remember the configuration on restart as well as provide the configuration to new servers that join servers remember the configuration on restart as well as provide the configuration to new servers that join the cluster
the cluster when it scales out. This feature is careful not to stomp on any existing region or index objects already when it is scaled out. This feature is careful not to stomp on any existing Region or Index objects already defined on
present on the servers, particularly since you may already have data stored in the regions. the servers, particularly since you may already have critical data stored in the Regions.
The primary motivation behind the `@EnableClusterAware` annotation is to let you switch environments with minimal The primary motivation for the `@EnableClusterAware` annotation is to let you switch environments with minimal effort.
effort. It is a common development practice to debug and test your application locally (in your IDE) and It is a common development practice to debug and test your application locally (in your IDE) and then push up to a
then push up to a production-like environment for more rigorous integration testing. production-like (staging) environment for more rigorous integration testing.
By default, the configuration metadata is sent to the cluster by using a non-secure HTTP connection. However, you can configure By default, the configuration metadata is sent to the cluster by using a non-secure HTTP connection. However, you can
HTTPS, change the host and port, and configure the data management policy used by the servers when creating regions. configure HTTPS, change the host and port, and configure the data management policy used by the servers when creating
Regions.
TIP: See the section in the SDG Reference Guide on TIP: See the section in the SDG reference documentation on
{spring-data-geode-docs-html}/#bootstrap-annotation-config-cluster[Configuring Cluster Configuration Push] {spring-data-geode-docs-html}/#bootstrap-annotation-config-cluster[Configuring Cluster Configuration Push]
for more details. for more details.
@@ -189,12 +193,12 @@ for more details.
The `strictMatch` attribute has been added to the `@EnableClusterAware` annotation to enable fail-fast behavior. The `strictMatch` attribute has been added to the `@EnableClusterAware` annotation to enable fail-fast behavior.
`strictMatch` is set to `false` by default. `strictMatch` is set to `false` by default.
Essentially, when you set `strictMatch` to `true`, your Spring Boot, {geode-name} `ClientCache` Essentially, when you set `strictMatch` to `true`, your Spring Boot, {geode-name} `ClientCache` application requires
application requires an {geode-name} cluster to exist. That is, the application requires a client/server topology an {geode-name} cluster to exist. That is, the application requires a client/server topology to operate, and the
to operate, and the application should fail to start if a cluster is not present. The application application should fail to start if a cluster is not present. The application should not startup in a local-only
should not startup in a local-only capacity. capacity.
When `strictMatch` is set to `true` and an {geode-name} cluster is not present, your Spring Boot, {geode-name} When `strictMatch` is set to `true` and an {geode-name} cluster is not available, your Spring Boot, {geode-name}
`ClientCache` application fails to start with a `ClusterNotFoundException`. The application does not attempt to `ClientCache` application fails to start with a `ClusterNotFoundException`. The application does not attempt to
start in a local-only capacity. start in a local-only capacity.
@@ -210,7 +214,8 @@ class SpringBootApacheGeodeClientCacheApplication { }
---- ----
==== ====
Alternatively, you can set `strictMatch` by using the corresponding property in Spring Boot `application.properties`: Alternatively, you can set `strictMatch` attribute by using the corresponding property
in Spring Boot `application.properties`:
.Set `strictMatch` using a property .Set `strictMatch` using a property
==== ====
@@ -222,12 +227,11 @@ spring.boot.data.gemfire.cluster.condition.match.strict=true
---- ----
==== ====
This is convenient when you need to apply this configuration setting conditionally, based on a Spring Profile. This is convenient when you need to apply this configuration setting conditionally, based on a Spring profile.
When you adjust the log level of the `org.springframework.geode.config.annotation.ClusterAwareConfiguration` logger When you adjust the log level of the `org.springframework.geode.config.annotation.ClusterAwareConfiguration` logger
to `INFO`, you get more details from the `@EnableClusterAware` functionality when applying the logic to `INFO`, you get more details from the `@EnableClusterAware` functionality when applying the logic to determine
to determine the presence of an {geode-name} cluster, such as which explicitly or implicitly configured connections the presence of an {geode-name} cluster, such as which explicitly or implicitly configured connections were successful.
were successful.
The following example shows typical output: The following example shows typical output:
@@ -243,8 +247,8 @@ The following example shows typical output:
---- ----
==== ====
NOTE: An attempt is always made to connect to `localhost` on the default locator port, `10334`, NOTE: An attempt is always made to connect to `localhost` on the default `Locator` port, `10334`, and the default
and the default `CacheServer` port, `40404`. `CacheServer` port, `40404`.
TIP: You can force a successful match by setting the `spring.boot.data.gemfire.cluster.condition.match` property TIP: You can force a successful match by setting the `spring.boot.data.gemfire.cluster.condition.match` property
to `true` in Spring Boot `application.properties`. This is sometimes useful for testing purposes. to `true` in Spring Boot `application.properties`. This is sometimes useful for testing purposes.
@@ -252,9 +256,9 @@ to `true` in Spring Boot `application.properties`. This is sometimes useful for
[[geode-configuration-declarative-annotations-productivity-regions]] [[geode-configuration-declarative-annotations-productivity-regions]]
==== `@EnableCachingDefinedRegions`, `@EnableClusterDefinedRegions` and `@EnableEntityDefinedRegions` (SDG) ==== `@EnableCachingDefinedRegions`, `@EnableClusterDefinedRegions` and `@EnableEntityDefinedRegions` (SDG)
These annotations are used to create regions in the cache to manage your application data. These annotations are used to create Regions in the cache to manage your application data.
You can create regions by using Java configuration and the Spring API as follows: You can create Regions by using Java configuration and the Spring API as follows:
.Creating a Region with Spring JavaConfig .Creating a Region with Spring JavaConfig
==== ====
@@ -263,16 +267,17 @@ You can create regions by using Java configuration and the Spring API as follows
@Configuration @Configuration
class GeodeConfiguration { class GeodeConfiguration {
@Bean("Customers") @Bean("Customers")
ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) { ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) {
ClientRegionFactoryBean<Long, Customer> customers = new ClientRegionFactoryBean<>(); ClientRegionFactoryBean<Long, Customer> customers =
new ClientRegionFactoryBean<>();
customers.setCache(cache); customers.setCache(cache);
customers.setShortcut(ClientRegionShortcut.PROXY); customers.setShortcut(ClientRegionShortcut.PROXY);
return customers; return customers;
} }
} }
---- ----
==== ====
@@ -287,16 +292,18 @@ You can do the same in XML:
---- ----
==== ====
However, using the provided annotations is far easier, especially during development, when the complete region However, using the provided annotations is far easier, especially during development, when the complete Region
configuration may be unknown and you want only to create a region to persist your application data and move on. configuration may be unknown and you want only to create a Region to persist your application data and move on.
[[geode-configuration-declarative-annotations-productivity-regions-enablecachingdefined]] [[geode-configuration-declarative-annotations-productivity-regions-enablecachingdefined]]
===== `@EnableCachingDefinedRegions` ===== `@EnableCachingDefinedRegions`
The `@EnableCachingDefinedRegions` annotation is used when you have application components registered in the Spring The `@EnableCachingDefinedRegions` annotation is used when you have application components registered in the Spring
container that are annotated with Spring or JSR-107 JCache {spring-framework-docs}/integration.html#cache-jsr-107[annotations]. container that are annotated with Spring or JSR-107 JCache
{spring-framework-docs}/integration.html#cache-jsr-107[annotations].
Caches that are identified by name in the caching annotations are used to create regions that hold the data you want cached. Caches that are identified by name in the caching annotations are used to create Regions that hold the data
you want cached.
Consider the following example: Consider the following example:
@@ -307,15 +314,16 @@ Consider the following example:
@Service @Service
class CustomerService { class CustomerService {
@Cacheable(cacheNames = "CustomersByAccountNumber", key = "#account.number") @Cacheable(cacheNames = "CustomersByAccountNumber", key = "#account.number")
Customer findBy(Account account) { Customer findBy(Account account) {
// ... // ...
} }
} }
---- ----
==== ====
Further consider the following example, in which the main `@SpringBootApplication` class is annotated with `@EnableCachingDefinedRegions`: Further consider the following example, in which the main `@SpringBootApplication` class is annotated with
`@EnableCachingDefinedRegions`:
.Using `@EnableCachingDefinedRegions` .Using `@EnableCachingDefinedRegions`
==== ====
@@ -327,24 +335,25 @@ class SpringBootApacheGeodeClientCacheApplication { }
---- ----
==== ====
With this setup, SBDG would create a client `PROXY` Region (or `PARTITION_REGION` if your application were a peer member of the With this setup, SBDG would create a client `PROXY` Region (or `PARTITION_REGION` if your application were a peer member
cluster) with a name of `CustomersByAccountNumber`, as though you created the region by using either the Java configuration or XML of the {geode-name} cluster) with a name of "`CustomersByAccountNumber`", as though you created the Region by using
approaches shown earlier. either the Java configuration or XML approaches shown earlier.
You can use the `clientRegionShortcut` or `serverRegionShortcut` attribute to change the data management policy of the You can use the `clientRegionShortcut` or `serverRegionShortcut` attribute to change the data management policy of
regions created on the client or servers, respectively. the Regions created on the client or servers, respectively.
For client regions, you can also set the `poolName` attribute to assign a specific pool of connections For client Regions, you can also set the `poolName` attribute to assign a specific `Pool` of connections to be used by
to be used by the client `*PROXY` regions to send data to the cluster. the client `*PROXY` Regions to send data to the cluster.
[[geode-configuration-declarative-annotations-productivity-regions-enableentitydefined]] [[geode-configuration-declarative-annotations-productivity-regions-enableentitydefined]]
===== `@EnableEntityDefinedRegions` ===== `@EnableEntityDefinedRegions`
As with `@EnableCachingDefinedRegions`, `@EnableEntityDefinedRegions` lets you create regions based on the entity As with `@EnableCachingDefinedRegions`, `@EnableEntityDefinedRegions` lets you create Regions based on the entity
classes you have defined in your application domain model. classes you have defined in your application domain model.
For instance, consider an entity class annotated with SDG's For instance, consider an entity class annotated with SDG's
{spring-data-geode-javadoc}/org/springframework/data/gemfire/mapping/annotation/Region.html[`@Region`] mapping annotation: {spring-data-geode-javadoc}/org/springframework/data/gemfire/mapping/annotation/Region.html[`@Region`]
mapping annotation:
.Customer entity class annotated with `@Region` .Customer entity class annotated with `@Region`
==== ====
@@ -353,19 +362,19 @@ For instance, consider an entity class annotated with SDG's
@Region("Customers") @Region("Customers")
class Customer { class Customer {
@Id @Id
private Long id; private Long id;
@Indexed @Indexed
private String name; private String name;
} }
---- ----
==== ====
For this class, SBDG creates regions from the name specified in the `@Region` mapping annotation on the entity class. In this For this class, SBDG creates Regions from the name specified in the `@Region` mapping annotation on the entity class.
case, the `Customer` application-defined entity class results in the creation of a region named `Customers` when In this case, the `Customer` application-defined entity class results in the creation of a Region named "`Customers`"
the main `@SpringBootApplication` class is annotated with `@EnableEntityDefinedRegions`: when the main `@SpringBootApplication` class is annotated with `@EnableEntityDefinedRegions`:
.Using `@EnableEntityDefinedRegions` .Using `@EnableEntityDefinedRegions`
==== ====
@@ -378,13 +387,12 @@ class SpringBootApacheGeodeClientCacheApplication { }
---- ----
==== ====
As with the `@EnableCachingDefinedRegions` annotation, you can set the client and server region data management policy As with the `@EnableCachingDefinedRegions` annotation, you can set the client and server Region data management policy
by using the `clientRegionShortcut` and `serverRegionShortcut` attributes, respectively, and set a dedicated pool by using the `clientRegionShortcut` and `serverRegionShortcut` attributes, respectively, and set a dedicated `Pool`
of connections used by client regions with the `poolName` attribute. of connections used by client Regions with the `poolName` attribute.
However, unlike the `@EnableCachingDefinedRegions` annotation, you must specify either the `basePackage` attribute However, unlike the `@EnableCachingDefinedRegions` annotation, you must specify either the `basePackage` attribute
or the type-safe `basePackageClasses` attribute (recommended) when you use the `@EnableEntityDefinedRegions` or the type-safe `basePackageClasses` attribute (recommended) when you use the `@EnableEntityDefinedRegions` annotation.
annotation.
Part of the reason for this is that `@EnableEntityDefinedRegions` performs a component scan for the entity classes Part of the reason for this is that `@EnableEntityDefinedRegions` performs a component scan for the entity classes
defined by your application. The component scan loads each class to inspect the annotation metadata for that class. defined by your application. The component scan loads each class to inspect the annotation metadata for that class.
@@ -393,10 +401,10 @@ This is not unlike the JPA entity scan when working with JPA providers, such as
Therefore, it is customary to limit the scope of the scan. Otherwise, you end up potentially loading many classes Therefore, it is customary to limit the scope of the scan. Otherwise, you end up potentially loading many classes
unnecessarily. After all, the JVM uses dynamic linking to load classes only when needed. unnecessarily. After all, the JVM uses dynamic linking to load classes only when needed.
Both the `basePackages` and `basePackageClasses` attributes accept an array of values. With `basePackageClasses`, you Both the `basePackages` and `basePackageClasses` attributes accept an array of values. With `basePackageClasses`, you
need only refer to a single class type in that package and every class in that package as well as classes in the need only refer to a single class type in that package and every class in that package as well as classes in the
sub-packages are scanned to determine if the class type represents an entity. A class type is an entity if it sub-packages are scanned to determine if the class type represents an entity. A class type is an entity if it is
is annotated with the `@Region` mapping annotation. Otherwise, it is not considered to be an entity. annotated with the `@Region` mapping annotation. Otherwise, it is not considered to be an entity.
For example, suppose you had the following structure: For example, suppose you had the following structure:
@@ -432,20 +440,21 @@ class SpringBootApacheGeodeClientCacheApplication { }
==== ====
If `Customer`, `Address`, `PhoneNumber` and `Account` were all entity classes properly annotated with `@Region`, If `Customer`, `Address`, `PhoneNumber` and `Account` were all entity classes properly annotated with `@Region`,
the component scan would pick up all these classes and create regions for them. The `NonEntity` class serves only as the component scan would pick up all these classes and create Regions for them. The `NonEntity` class serves only as
a marker in this case, to point to where (that is, which package) the scan should begin. a marker in this case, to point to where (that is, which package) the scan should begin.
Additionally, the `@EnableEntityDefinedRegions` annotation provides include and exclude filters, the same as Additionally, the `@EnableEntityDefinedRegions` annotation provides include and exclude filters, the same as
the core Spring Frameworks `@ComponentScan` annotation. the core Spring Frameworks `@ComponentScan` annotation.
TIP: See the SDG Reference Guide on {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[Configuring Regions] TIP: See the SDG reference documentation on
{spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[Configuring Regions]
for more details. for more details.
[[geode-configuration-declarative-annotations-productivity-regions-enableclusterdefined]] [[geode-configuration-declarative-annotations-productivity-regions-enableclusterdefined]]
===== `@EnableClusterDefinedRegions` ===== `@EnableClusterDefinedRegions`
Sometimes, it is ideal or even necessary to pull configuration from the cluster (rather than push to the cluster). Sometimes, it is ideal or even necessary to pull configuration from the cluster (rather than push configuration to the
That is, you want the regions defined on the servers to be created on the client and used by your application. cluster). That is, you want the Regions defined on the servers to be created on the client and used by your application.
To do so, annotate your main `@SpringBootApplication` class with `@EnableClusterDefinedRegions`: To do so, annotate your main `@SpringBootApplication` class with `@EnableClusterDefinedRegions`:
@@ -459,11 +468,11 @@ class SpringBootApacheGeodeClientCacheApplication { }
---- ----
==== ====
Every region that exists on the cluster of servers has a corresponding `PROXY` region defined and created on the Every Region that exists on the servers in the {geode-name} cluster will have a corresponding `PROXY` Region defined
client as a bean in your Spring Boot application. and created on the client as a bean in your Spring Boot application.
If the cluster of servers defines a region called `ServerRegion`, you can inject a client `PROXY` region If the cluster of servers defines a Region called "`ServerRegion`", you can inject a client `PROXY` Region with
with the same name (`ServerRegion`) into your Spring Boot application: the same name ("`ServerRegion`") into your Spring Boot application:
.Using a server-side Region on the client .Using a server-side Region on the client
==== ====
@@ -472,23 +481,24 @@ with the same name (`ServerRegion`) into your Spring Boot application:
@Component @Component
class SomeApplicationComponent { class SomeApplicationComponent {
@Resource(name = "ServerRegion") @Resource(name = "ServerRegion")
private Region<Integer, EntityType> serverRegion; private Region<Integer, EntityType> serverRegion;
public void someMethod() { public void someMethod() {
EntityType entity = new EntityType(); EntityType entity = new EntityType();
this.serverRegion.put(1, entity); this.serverRegion.put(1, entity);
// ... // ...
} }
} }
---- ----
==== ====
SBDG auto-configures a `GemfireTemplate` for the `ServerRegion` region (see <<geode-configuration-declarative-auto-configuration-regiontemplates,>>), SBDG auto-configures a `GemfireTemplate` for the "`ServerRegion`" Region
so a better way to interact with the client `PROXY` region that corresponds to the `ServerRegion` region on the server (see <<geode-configuration-declarative-auto-configuration-regiontemplates>>),
so a better way to interact with the client `PROXY` Region that corresponds to the "`ServerRegion`" Region on the server
is to inject the template: is to inject the template:
.Using a server-side Region on the client with a template .Using a server-side Region on the client with a template
@@ -498,43 +508,46 @@ is to inject the template:
@Component @Component
class SomeApplicationComponent { class SomeApplicationComponent {
@Autowired @Autowired
@Qualifier("serverRegionTemplate") @Qualifier("serverRegionTemplate")
private GemfireTemplate serverRegionTemplate; private GemfireTemplate serverRegionTemplate;
public void someMethod() { public void someMethod() {
EntityType entity = new EntityType(); EntityType entity = new EntityType();
this.serverRegionTemplate.put(1, entity); this.serverRegionTemplate.put(1, entity);
//... //...
} }
} }
---- ----
==== ====
TIP: See the SDG Reference Guide on {spring-data-geode-docs-html}/#bootstrap-annotation-config-region-cluster-defined[Configuring Cluster-defined Regions] TIP: See the SDG reference documentation on
{spring-data-geode-docs-html}/#bootstrap-annotation-config-region-cluster-defined[Configuring Cluster-defined Regions]
for more details. for more details.
[[geode-configuration-declarative-annotations-productivity-enableindexing]] [[geode-configuration-declarative-annotations-productivity-enableindexing]]
==== `@EnableIndexing` (SDG) ==== `@EnableIndexing` (SDG)
You can also use the `@EnableIndexing` annotation -- but only when you use `@EnableEntityDefinedRegions`. This is because You can also use the `@EnableIndexing` annotation -- but only when you use `@EnableEntityDefinedRegions`. This is
`@EnableIndexing` requires the entities to be scanned and analyzed for mapping metadata (defined on the class type because `@EnableIndexing` requires the entities to be scanned and analyzed for mapping metadata (defined on the class
of the entity). This includes annotations such as the Spring Data Commons `@Id` annotation a the annotations provided by SDG: type of the entity). This includes annotations such as the Spring Data Commons `@Id` annotation and the annotations
`@Indexed` and `@LuceneIndexed`. provided by SDG, such as `@Indexed` and `@LuceneIndexed`.
The `@Id` annotation identifies the (primary) key of the entity. The `@Indexed` annotation defines OQL indexes on object fields, The `@Id` annotation identifies the (primary) key of the entity. The `@Indexed` annotation defines OQL indexes on object
which are used in the predicates of your OQL Queries. The `@LuceneIndexed` annotation is used to define the Apache Lucene fields, which can be used in the predicates of your OQL queries. The `@LuceneIndexed` annotation is used to define the
indexes required for searches. Apache Lucene Indexes required for searches.
NOTE: Lucene Indexes can only be created on `PARTITION` regions, and `PARTITION` regions are only defined NOTE: Lucene Indexes can only be created on `PARTITION` Regions, and `PARTITION` Regions can only be defined on
on the server side. the server side.
You may have noticed that the `Customer` entity class's `name` field was annotated with `@Indexed`. You may have noticed that the `Customer` entity class's `name` field was annotated with `@Indexed`.
Consider the following listing: Consider the following listing:
Consider the following listing:
.Customer entity class with `@Indexed` annotated `name` field .Customer entity class with `@Indexed` annotated `name` field
==== ====
[source,java] [source,java]
@@ -542,19 +555,18 @@ Consider the following listing:
@Region("Customers") @Region("Customers")
class Customer { class Customer {
@Id @Id
private Long id; private Long id;
@Indexed @Indexed
private String name; private String name;
} }
---- ----
==== ====
As a result, when our main `@SpringBootApplication` class is annotated with `@EnableIndexing`, As a result, when our main `@SpringBootApplication` class is annotated with `@EnableIndexing`, an {geode-name} OQL Index
an {geode-name} OQL index for the `Customer.name` field is created, making OQL Queries on customers by name for the `Customer.name` field is created, allowing OQL queries on customers by name to use this Index:
use this index:
.Using `@EnableIndexing` .Using `@EnableIndexing`
==== ====
@@ -567,48 +579,49 @@ class SpringBootApacheGeodeClientCacheApplication { }
---- ----
==== ====
NOTE: Keep in mind that OQL Indexes are not persistent between restarts (that is, {geode-name} maintains indexes in memory NOTE: Keep in mind that OQL Indexes are not persistent between restarts (that is, {geode-name} maintains Indexes
only). An OQL Index is always rebuilt when the node is restarted. in memory only). An OQL Index is always rebuilt when the node is restarted.
When you combine `@EnableIndexing` with either `@EnableClusterConfiguration` or `@EnableClusterAware`, the index When you combine `@EnableIndexing` with either `@EnableClusterConfiguration` or `@EnableClusterAware`, the Index
definitions are pushed to the server-side regions where OQL Queries are generally executed. definitions are pushed to the server-side Regions where OQL queries are generally executed.
TIP: See the SDG Reference Guide on {spring-data-geode-docs-html}/#bootstrap-annotation-config-region-indexes[Configuring Indexes] TIP: See the SDG reference documentation on
{spring-data-geode-docs-html}/#bootstrap-annotation-config-region-indexes[Configuring Indexes]
for more details. for more details.
[[geode-configuration-declarative-annotations-productivity-enableexpiration]] [[geode-configuration-declarative-annotations-productivity-enableexpiration]]
==== `@EnableExpiration` (SDG) ==== `@EnableExpiration` (SDG)
It is often useful to define both eviction and expiration policies, particularly with a system like {geode-name}, It is often useful to define both eviction and expiration policies, particularly with a system like {geode-name},
because it primarily keeps data in memory (on the JVM heap). Your data volume size may far because it primarily keeps data in memory (on the JVM Heap). Your data volume size may far exceed the amount of
exceed the amount of available JVM heap memory, and keeping too much data on the JVM Heap can cause Garbage Collection available JVM Heap memory, and keeping too much data on the JVM Heap can cause Garbage Collection (GC) issues.
(GC) issues.
TIP: You can enable off-heap (or main memory usage) capabilities by declaring SDG's `@EnableOffHeap` annotation. TIP: You can enable off-heap (or main memory usage) capabilities by declaring SDG's `@EnableOffHeap` annotation.
See the SDG Reference Guide on {spring-data-geode-docs-html}/#bootstrap-annotation-config-region-off-heap[Configuring Off-Heap Memory] See the SDG reference documentation on
{spring-data-geode-docs-html}/#bootstrap-annotation-config-region-off-heap[Configuring Off-Heap Memory]
for more details. for more details.
Defining eviction and expiration policies lets you limit what is kept in memory and for how long. Defining eviction and expiration policies lets you limit what is kept in memory and for how long.
While {spring-data-geode-docs-html}/#bootstrap-annotation-config-region-eviction[configuring eviction] is easy with While {spring-data-geode-docs-html}/#bootstrap-annotation-config-region-eviction[configuring eviction] is easy with SDG,
SDG, we particularly want to call out expiration since we particularly want to call out expiration since
{spring-data-geode-docs-html}/#bootstrap-annotation-config-region-expiration[configuring expiration] has special {spring-data-geode-docs-html}/#bootstrap-annotation-config-region-expiration[configuring expiration] has special support
support in SDG. in SDG.
With SDG, you can define the expiration policies associated with a particular application class type on the With SDG, you can define the expiration policies associated with a particular application class type on the class type
class type itself, by using the {spring-data-geode-javadoc}/org/springframework/data/gemfire/expiration/Expiration.html[`@Expiration`], itself, by using the {spring-data-geode-javadoc}/org/springframework/data/gemfire/expiration/Expiration.html[`@Expiration`],
{spring-data-geode-javadoc}/org/springframework/data/gemfire/expiration/IdleTimeoutExpiration.html[`@IdleTimeoutExpiration`], {spring-data-geode-javadoc}/org/springframework/data/gemfire/expiration/IdleTimeoutExpiration.html[`@IdleTimeoutExpiration`]
and {spring-data-geode-javadoc}/org/springframework/data/gemfire/expiration/TimeToLiveExpiration.html[`@TimeToLiveExpiration`] and {spring-data-geode-javadoc}/org/springframework/data/gemfire/expiration/TimeToLiveExpiration.html[`@TimeToLiveExpiration`]
annotations. annotations.
TIP: See the {geode-name} {apache-geode-docs}/developing/expiration/how_expiration_works.html[User Guide] TIP: See the {geode-name} {apache-geode-docs}/developing/expiration/how_expiration_works.html[User Guide]
for more details on the different expiration types -- that is idle timeout (TTI) versus time-to-live (TTL). for more details on the different expiration types -- that is _Idle Timeout_ (TTI) versus _Time-to-Live_ (TTL).
For example, suppose we want to limit the number of `Customers` maintained in memory for a period of time (measured in For example, suppose we want to limit the number of `Customers` maintained in memory for a period of time (measured in
seconds) based on the last time a `Customer` was accessed (for example, the last time it was read). To do so, we can define an idle timeout expiration seconds) based on the last time a `Customer` was accessed (for example, the last time a `Customer` was read). To do so,
policy on our `Customer` class type: we can define an idle timeout expiration (TTI) policy on our `Customer` class type:
.Customer entity class with `@Indexed` annotated `name` field .Customer entity class with Idle Timeout Expiration (TTI)
==== ====
[source,java] [source,java]
---- ----
@@ -616,11 +629,11 @@ policy on our `Customer` class type:
@IdleTimeoutExpiration(action = "INVALIDATE", timeout = "300") @IdleTimeoutExpiration(action = "INVALIDATE", timeout = "300")
class Customer { class Customer {
@Id @Id
private Long id; private Long id;
@Indexed @Indexed
private String name; private String name;
} }
---- ----
@@ -644,29 +657,29 @@ class SpringBootApacheGeodeApplication { }
NOTE: Technically, this entity-class-specific annotation-based expiration policy is implemented by using {geode-name}'s NOTE: Technically, this entity-class-specific annotation-based expiration policy is implemented by using {geode-name}'s
{apache-geode-javadoc}/org/apache/geode/cache/CustomExpiry.html[`CustomExpiry`] interface. {apache-geode-javadoc}/org/apache/geode/cache/CustomExpiry.html[`CustomExpiry`] interface.
TIP: See the SDG Reference Guide for more details on TIP: See the SDG reference doccumentation for more details on
{spring-data-geode-docs-html}/#bootstrap-annotation-config-region-expiration[configuring Expiration], along with {spring-data-geode-docs-html}/#bootstrap-annotation-config-region-expiration[configuring expiration], along with
{spring-data-geode-docs-html}/#bootstrap:region:expiration:annotation[Annotation-based Data Expiration] in particular. {spring-data-geode-docs-html}/#bootstrap:region:expiration:annotation[annotation-based data expiration] in particular.
[[geode-configuration-declarative-annotations-productivity-enablemockobjects]] [[geode-configuration-declarative-annotations-productivity-enablemockobjects]]
==== `@EnableGemFireMockObjects` (STDG) ==== `@EnableGemFireMockObjects` (STDG)
Software testing in general and unit testing in particular are a very important development tasks to ensure Software testing in general and unit testing in particular are a very important development tasks to ensure the quality
the quality of your Spring Boot applications. of your Spring Boot applications.
{geode-name} can make testing difficult in some cases, especially when tests have to be written as integration tests {geode-name} can make testing difficult in some cases, especially when tests have to be written as integration tests
to assert the correct behavior. This can be very costly and lengthens the feedback cycle. Fortunately, you to assert the correct behavior. This can be very costly and lengthens the feedback cycle. Fortunately, you can write
can write unit tests as well. unit tests as well.
Spring provides a framework for testing Spring Boot applications that use {geode-name}. This Spring provides a framework for testing Spring Boot applications that use {geode-name}. This is where the
is where the {spring-test-data-gemfire-website}[Spring Test for {geode-name} (STDG)] project can help, particularly with {spring-test-data-gemfire-website}[Spring Test for {geode-name} (STDG)] project can help, particularly with
unit testing. unit testing.
For example, if you do not care what {geode-name} would actually do in certain cases and only care about the "`contract`", For example, if you do not care what {geode-name} would actually do in certain cases and only care about the "`contract`",
which is what mocking a collaborator is all about, you could effectively mock {geode-name} objects to which is what mocking a collaborator is all about, you could effectively mock {geode-name} objects to isolate the SUT,
isolate the "`Subject Under Test`" (SUT) and focus on the interactions or outcomes you expect to happen. or "`Subject Under Test`", and focus on the interactions or outcomes you expect to happen.
With STDG, you need not change a bit of configuration to enable mocks in the unit tests for your Spring Boot With STDG, you need not change a bit of configuration to enable mock objects in the unit tests for your Spring Boot
applications. You need only annotate the test class with `@EnableGemFireMockObjects`: applications. You need only annotate the test class with `@EnableGemFireMockObjects`:
.Using Mock {geode-name} Objects .Using Mock {geode-name} Objects
@@ -677,20 +690,20 @@ applications. You need only annotate the test class with `@EnableGemFireMockObje
@SpringBootTest @SpringBootTest
class MyApplicationTestClass { class MyApplicationTestClass {
@Test @Test
public void someTestCase() { public void someTestCase() {
// ... // ...
} }
@Configuration @Configuration
@EnableGemFireMockObjects @EnableGemFireMockObjects
static class GeodeConfiguration { } static class GeodeConfiguration { }
} }
---- ----
==== ====
Your Spring Boot configuration of {geode-name} returns mock objects for all {geode-name} objects, such as regions. Your Spring Boot configuration of {geode-name} returns mock objects for all {geode-name} objects, such as Regions.
Mocking {geode-name} objects even works for objects created from the productivity annotations discussed in the previous Mocking {geode-name} objects even works for objects created from the productivity annotations discussed in the previous
sections. sections.
@@ -707,9 +720,9 @@ class SpringBootApacheGeodeClientCacheApplication { }
---- ----
==== ====
In the preceding example, the `Customers` region defined by the `Customer` entity class and created by the `@EnableEntityDefinedRegions` In the preceding example, the `"Customers`" Region defined by the `Customer` entity class and created by
annotation would be a "`mock`" region and not an actual region. You can still inject the region in your test the `@EnableEntityDefinedRegions` annotation would be a mock Region and not an actual Region. You can still inject
and assert interactions on the region based on your application workflows: the Region in your test and assert interactions on the Region based on your application workflows:
.Using Mock {geode-name} Objects .Using Mock {geode-name} Objects
==== ====
@@ -719,30 +732,30 @@ and assert interactions on the region based on your application workflows:
@SpringBootTest @SpringBootTest
class MyApplicationTestClass { class MyApplicationTestClass {
@Resource(name = "Customers") @Resource(name = "Customers")
private Region<Long, Customer> customers; private Region<Long, Customer> customers;
@Test @Test
public void someTestCase() { public void someTestCase() {
Customer jonDoe = new Customer(1, "Jon Doe"); Customer jonDoe = new Customer(1, "Jon Doe");
// Use the application in some way and test the interaction on the "Customers" Region // Use the application in some way and test the interaction on the "Customers" Region
assertThat(this.customers).containsValue(jonDoe); assertThat(this.customers).containsValue(jonDoe);
// ... // ...
} }
} }
---- ----
==== ====
There are many more things that STDG can do for you in both unit testing and integration testing. There are many more things that STDG can do for you in both unit testing and integration testing.
See the https://github.com/spring-projects/spring-test-data-geode#unit-testing-with-stdg[documentation on Unit Testing] See the https://github.com/spring-projects/spring-test-data-geode#unit-testing-with-stdg[documentation on unit testing]
for more details. for more details.
You can https://github.com/spring-projects/spring-test-data-geode#integration-testing-with-stdg[write integration tests] You can https://github.com/spring-projects/spring-test-data-geode#integration-testing-with-stdg[write integration tests]
that use STDG as well. Writing integration tests is an essential concern when you need to assert whether your that use STDG as well. Writing integration tests is an essential concern when you need to assert whether your
application OQL Queries are well-formed, for instance. There are many other valid cases where integration testing application OQL queries are well-formed, for instance. There are many other valid cases where integration testing
is also applicable. is also applicable.

View File

@@ -3,13 +3,13 @@
:geode-name: {apache-geode-name} :geode-name: {apache-geode-name}
Like Spring Boot itself (see {spring-boot-docs-html}/boot-features-external-config.html[Spring Boot's documentation]), Spring Boot Like Spring Boot itself (see {spring-boot-docs-html}/boot-features-external-config.html[Spring Boot's documentation]),
for {geode-name} (SBDG) supports externalized configuration. Spring Boot for {geode-name} (SBDG) supports externalized configuration.
By externalized configuration, we mean configuration metadata stored in a Spring Boot By externalized configuration, we mean configuration metadata stored in Spring Boot
{spring-boot-docs-html}/boot-features-external-config.html#boot-features-external-config-application-property-files[`application.properties` file], {spring-boot-docs-html}/boot-features-external-config.html#boot-features-external-config-application-property-files[`application.properties`].
for instance. You can even separate concerns by addressing each concern in an individual properties file. Optionally, you could also You can even separate concerns by addressing each concern in an individual properties file. Optionally, you could also
enable any given property file for only a specific {spring-boot-docs-html}/boot-features-external-config.html#boot-features-external-config-profile-specific-properties[Profile]. enable any given property file for only a specific {spring-boot-docs-html}/boot-features-external-config.html#boot-features-external-config-profile-specific-properties[profile].
You can do many other powerful things, such as (but not limited to) using You can do many other powerful things, such as (but not limited to) using
{spring-boot-docs-html}/boot-features-external-config.html#boot-features-external-config-placeholders-in-properties[placeholders] {spring-boot-docs-html}/boot-features-external-config.html#boot-features-external-config-placeholders-in-properties[placeholders]
@@ -21,7 +21,7 @@ Like Spring Boot, Spring Boot for {geode-name} provides a hierarchy of classes t
{geode-name} features in an associated `@ConfigurationProperties` annotated class. Again, the configuration metadata is {geode-name} features in an associated `@ConfigurationProperties` annotated class. Again, the configuration metadata is
specified as well-known, documented properties in one or more Spring Boot `application.properties` files. specified as well-known, documented properties in one or more Spring Boot `application.properties` files.
For instance, a Spring Boot, `ClientCache` application might be configured as follows: For instance, a Spring Boot, {geode-name} `ClientCache` application might be configured as follows:
.Spring Boot `application.properties` containing Spring Data properties for {geode-name} .Spring Boot `application.properties` containing Spring Data properties for {geode-name}
==== ====
@@ -47,14 +47,14 @@ spring.data.gemfire.pool.locators=10.105.120.16[11235],boombox[10334]
---- ----
==== ====
You can use many other properties to externalize the configuration of your Spring Boot, You can use many other properties to externalize the configuration of your Spring Boot, {geode-name} applications.
{geode-name} applications. See the See the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-frame.html[Javadoc]
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-frame.html[Javadoc]
for specific configuration properties. Specifically, review the `enabling` annotation attributes. for specific configuration properties. Specifically, review the `enabling` annotation attributes.
You may sometimes require access to the configuration metadata (specified in properties) You may sometimes require access to the configuration metadata (specified in properties) in your Spring Boot
in your Spring Boot applications themselves, perhaps to further inspect or act on a particular configuration setting. applications themselves, perhaps to further inspect or act on a particular configuration setting. You can access any
You can access any property by using Spring's {spring-framework-javadoc}/org/springframework/core/env/Environment.html[`Environment`] abstraction: property by using Spring's {spring-framework-javadoc}/org/springframework/core/env/Environment.html[`Environment`]
abstraction:
.Using the Spring `Environment` .Using the Spring `Environment`
==== ====
@@ -62,16 +62,18 @@ You can access any property by using Spring's {spring-framework-javadoc}/org/spr
---- ----
@Configuration @Configuration
class GeodeConfiguration { class GeodeConfiguration {
void readConfigurationFromEnvironment(Environment environment) {
boolean copyOnRead = environment.getProperty("spring.data.gemfire.cache.copy-on-read", Boolean.TYPE, false); void readConfigurationFromEnvironment(Environment environment) {
} boolean copyOnRead = environment.getProperty("spring.data.gemfire.cache.copy-on-read",
Boolean.TYPE, false);
}
} }
---- ----
==== ====
While using `Environment` is a nice approach, you might need access to additional properties or want to access While using `Environment` is a nice approach, you might need access to additional properties or want to access
the property values in a type-safe manner. Therefore, you can now, thanks to SBDG's auto-configured the property values in a type-safe manner. Therefore, you can now, thanks to SBDG's auto-configured configuration
configuration processor, access the configuration metadata by using `@ConfigurationProperties` classes. processor, access the configuration metadata by using `@ConfigurationProperties` classes.
To add to the preceding example, you can now do the following: To add to the preceding example, you can now do the following:
@@ -79,34 +81,34 @@ To add to the preceding example, you can now do the following:
==== ====
[source,java] [source,java]
---- ----
@Component @Component
class MyApplicationComponent { class MyApplicationComponent {
@Autowired @Autowired
private GemFireProperties gemfireProperties; private GemFireProperties gemfireProperties;
public void someMethodUsingGemFireProperties() { public void someMethodUsingGemFireProperties() {
boolean copyOnRead = this.gemfireProperties.getCache().isCopyOnRead(); boolean copyOnRead = this.gemfireProperties.getCache().isCopyOnRead();
// do something with `copyOnRead` // do something with `copyOnRead`
} }
} }
---- ----
==== ====
Given a handle to {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/GemFireProperties.html[`GemFireProperties`], Given a handle to {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/GemFireProperties.html[`GemFireProperties`],
you can access any of the configuration properties that are used to configure {geode-name} in a Spring context. You need only you can access any of the configuration properties that are used to configure {geode-name} in a Spring context. You need
autowire an instance of `GemFireProperties` into your application component. only autowire an instance of `GemFireProperties` into your application component.
See the complete reference for the {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/package-frame.html[SBDG `@ConfigurationProperties` classes and supporting classes]. See the complete reference for the
{spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/package-frame.html[SBDG `@ConfigurationProperties` classes and supporting classes].
[[geode-configuration-externalized-session]] [[geode-configuration-externalized-session]]
=== Externalized Configuration of Spring Session === Externalized Configuration of Spring Session
You can access the externalized configuration of Spring Session when you use {geode-name} as You can access the externalized configuration of Spring Session when you use {geode-name} as your (HTTP) session state
your (HTTP) Session state caching provider. caching provider.
In this case, you need only acquire a reference to an instance of the In this case, you need only acquire a reference to an instance of the
{spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/SpringSessionProperties.html[`SpringSessionProperties`] {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/SpringSessionProperties.html[`SpringSessionProperties`]
@@ -114,11 +116,12 @@ class.
As shown earlier in this chapter, you can specify Spring Session for {geode-name} (SSDG) properties as follows: As shown earlier in this chapter, you can specify Spring Session for {geode-name} (SSDG) properties as follows:
.Spring Boot `application.properties` for Spring Session using {geode-name} as the (HTTP) Session state caching provider .Spring Boot `application.properties` for Spring Session using {geode-name} as the (HTTP) session state caching provider
==== ====
[source,properties] [source,properties]
---- ----
# Spring Boot application.properties used to configure {geode-name} as a Session state caching provider in Spring Session # Spring Boot application.properties used to configure {geode-name} as a (HTTP) session state caching provider
# in Spring Session
spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds=300 spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds=300
spring.session.data.gemfire.session.region.name=UserSessions spring.session.data.gemfire.session.region.name=UserSessions
@@ -134,15 +137,16 @@ Then, in your application, you can do something similar to the following example
@Component @Component
class MyApplicationComponent { class MyApplicationComponent {
@Autowired @Autowired
private SpringSessionProperties springSessionProperties; private SpringSessionProperties springSessionProperties;
public void someMethodUsingSpringSessionProperties() { public void someMethodUsingSpringSessionProperties() {
String sessionRegionName = this.springSessionProperties.getSession().getRegion().getName(); String sessionRegionName = this.springSessionProperties
.getSession().getRegion().getName();
// do something with `sessionRegionName` // do something with `sessionRegionName`
} }
} }
---- ----
==== ====

View File

@@ -5,9 +5,12 @@
The following reference sections cover documented and well-known properties recognized and processed by The following reference sections cover documented and well-known properties recognized and processed by
Spring Data for {geode-name} (SDG) and Spring Session for {geode-name} (SSDG). Spring Data for {geode-name} (SDG) and Spring Session for {geode-name} (SSDG).
These properties may be used in Spring Boot `application.properties` files or as JVM System properties, to configure The following reference sections cover documented and well-known properties recognized and processed by Spring Data
different aspects of or enable individual features of {geode-name} in a Spring application. When combined with the power for {geode-name} (SDG) and Spring Session for {geode-name} (SSDG).
of Spring Boot, they give you the ability to quickly create an application that uses {geode_name}.
These properties may be used in Spring Boot `application.properties` or as JVM System properties, to configure different
aspects of or enable individual features of {geode-name} in a Spring application. When combined with the power of
Spring Boot, they give you the ability to quickly create an application that uses {geode_name}.
[[geode-configuration-metadata-springdata]] [[geode-configuration-metadata-springdata]]
=== Spring Data Based Properties === Spring Data Based Properties
@@ -15,7 +18,6 @@ of Spring Boot, they give you the ability to quickly create an application that
The following properties all have a `spring.data.gemfire.*` prefix. For example, to set the cache `copy-on-read` The following properties all have a `spring.data.gemfire.*` prefix. For example, to set the cache `copy-on-read`
property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `application.properties`. property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `application.properties`.
.`spring.data.gemfire.*` properties .`spring.data.gemfire.*` properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -27,7 +29,6 @@ property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `applicati
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` _GemFireCache_ properties .`spring.data.gemfire.*` _GemFireCache_ properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -36,19 +37,18 @@ property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `applicati
| `cache.copy-on-read` | Configure whether a copy of an object returned from `Region.get(key)` is made. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#copyOnRead--[`ClientCacheApplication.copyOnRead`] | `cache.copy-on-read` | Configure whether a copy of an object returned from `Region.get(key)` is made. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#copyOnRead--[`ClientCacheApplication.copyOnRead`]
| `cache.critical-heap-percentage` | Percentage of heap at or above which the cache is considered in danger of becoming inoperable. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#criticalHeapPercentage--[`ClientCacheApplication.criticalHeapPercentage`] | `cache.critical-heap-percentage` | Percentage of heap at or above which the cache is considered in danger of becoming inoperable. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#criticalHeapPercentage--[`ClientCacheApplication.criticalHeapPercentage`]
| `cache.critical-off-heap-percentage` | Percentage of off-heap at or above which the cache is considered in danger of becoming inoperable. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#criticalOffHeapPercentage--[`ClientCacheApplication.criticalOffHeapPercentage`] | `cache.critical-off-heap-percentage` | Percentage of off-heap at or above which the cache is considered in danger of becoming inoperable. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#criticalOffHeapPercentage--[`ClientCacheApplication.criticalOffHeapPercentage`]
| `cache.enable-auto-region-lookup` | Whether to lookup regions configured in {geode-name} native configuration and declare them as Spring beans. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAutoRegionLookup.html#enabled--[`EnableAutoRegionLookup.enable`] | `cache.enable-auto-region-lookup` | Whether to lookup Regions configured in {geode-name} native configuration and declare them as Spring beans. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAutoRegionLookup.html#enabled--[`EnableAutoRegionLookup.enable`]
| `cache.eviction-heap-percentage` | Percentage of heap at or above which the eviction should begin on regions configured for HeapLRU eviction. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#evictionHeapPercentage--[`ClientCacheApplication.evictionHeapPercentage`] | `cache.eviction-heap-percentage` | Percentage of heap at or above which the eviction should begin on Regions configured for HeapLRU eviction. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#evictionHeapPercentage--[`ClientCacheApplication.evictionHeapPercentage`]
| `cache.eviction-off-heap-percentage` | Percentage of off-heap at or above which the eviction should begin on regions configured for HeapLRU eviction. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#evictionOffHeapPercentage--[`ClientCacheApplication.evictionOffHeapPercentage`] | `cache.eviction-off-heap-percentage` | Percentage of off-heap at or above which the eviction should begin on Regions configured for HeapLRU eviction. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#evictionOffHeapPercentage--[`ClientCacheApplication.evictionOffHeapPercentage`]
| `cache.log-level` | Configure the log-level of an {geode-name} cache. | `config` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#logLevel--[`ClientCacheApplication.logLevel`] | `cache.log-level` | Configure the log-level of an {geode-name} cache. | `config` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#logLevel--[`ClientCacheApplication.logLevel`]
| `cache.name` | Alias for `spring.data.gemfire.name`. | `SpringBasedCacheClientApplication` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#name--[`ClientCacheApplication.name`] | `cache.name` | Alias for `spring.data.gemfire.name`. | `SpringBasedCacheClientApplication` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#name--[`ClientCacheApplication.name`]
| `cache.compression.bean-name` | Name of a Spring bean that implements `org.apache.geode.compression.Compressor`. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCompression.html#compressorBeanName--[`EnableCompression.compressorBeanName`] | `cache.compression.bean-name` | Name of a Spring bean that implements `org.apache.geode.compression.Compressor`. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCompression.html#compressorBeanName--[`EnableCompression.compressorBeanName`]
| `cache.compression.region-names` | Comma-delimited list of region names for which compression is configured. | `[]` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCompression.html#regionNames--[EnableCompression.regionNames] | `cache.compression.region-names` | Comma-delimited list of Region names for which compression is configured. | `[]` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCompression.html#RegionNames--[EnableCompression.RegionNames]
| cache.off-heap.memory-size | Determines the size of off-heap memory used by {geode-name} in megabytes (m) or gigabytes (g) -- for example, `120g` | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableOffHeap.html#memorySize--[`EnableOffHeap.memorySize`] | cache.off-heap.memory-size | Determines the size of off-heap memory used by {geode-name} in megabytes (m) or gigabytes (g) -- for example, `120g` | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableOffHeap.html#memorySize--[`EnableOffHeap.memorySize`]
| `cache.off-heap.region-names` | Comma-delimited list of region names for which off-heap is configured. | `[]` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableOffHeap.html#regionNames--[`EnableOffHeap.regionNames`] | `cache.off-heap.region-names` | Comma-delimited list of Region names for which off-heap is configured. | `[]` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableOffHeap.html#RegionNames--[`EnableOffHeap.RegionNames`]
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` _ClientCache_ properties .`spring.data.gemfire.*` _ClientCache_ properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -60,13 +60,12 @@ property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `applicati
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` peer _Cache_ properties .`spring.data.gemfire.*` peer _Cache_ properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Default | From | Name | Description | Default | From
| `cache.peer.enable-auto-reconnect` | Whether a member (a locator or server) try to reconnect and reinitialize the cache after it has been forced out of the cluster by a network partition event or has otherwise been shunned by other members. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html#enableAutoReconnect--[`PeerCacheApplication.enableAutoReconnect`] | `cache.peer.enable-auto-reconnect` | Whether a member (a Locator or Server) try to reconnect and reinitialize the cache after it has been forced out of the cluster by a network partition event or has otherwise been shunned by other members. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html#enableAutoReconnect--[`PeerCacheApplication.enableAutoReconnect`]
| `cache.peer.lock-lease` | The length, in seconds, of distributed lock leases obtained by this cache. | `120` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html#lockLease--[`PeerCacheApplication.lockLease`] | `cache.peer.lock-lease` | The length, in seconds, of distributed lock leases obtained by this cache. | `120` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html#lockLease--[`PeerCacheApplication.lockLease`]
| `cache.peer.lock-timeout` | The number of seconds a cache operation waits to obtain a distributed lock lease. | `60` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html#lockTimeout--[`PeerCacheApplication.lockTimeout`] | `cache.peer.lock-timeout` | The number of seconds a cache operation waits to obtain a distributed lock lease. | `60` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html#lockTimeout--[`PeerCacheApplication.lockTimeout`]
| `cache.peer.message-sync-interval` | The frequency (in seconds) at which a message is sent by the primary cache-server to all the secondary cache-server nodes to remove the events that have already been dispatched from the queue. | `1` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html#messageSyncInterval--[`PeerCacheApplication.messageSyncInterval`] | `cache.peer.message-sync-interval` | The frequency (in seconds) at which a message is sent by the primary cache-server to all the secondary cache-server nodes to remove the events that have already been dispatched from the queue. | `1` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html#messageSyncInterval--[`PeerCacheApplication.messageSyncInterval`]
@@ -75,7 +74,6 @@ property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `applicati
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` _CacheServer_ properties .`spring.data.gemfire.*` _CacheServer_ properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -99,8 +97,8 @@ property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `applicati
|===================================================================================================================== |=====================================================================================================================
`CacheServer` properties can be further targeted at specific `CacheServer` instances by using an option bean name `CacheServer` properties can be further targeted at specific `CacheServer` instances by using an optional bean name
of the `CacheServer` bean defined in the Spring application context. Consider the following example: of the `CacheServer` bean defined in the Spring `ApplicationContext`. Consider the following example:
==== ====
[source,properties] [source,properties]
@@ -109,23 +107,21 @@ spring.data.gemfire.cache.server.[<cacheServerBeanName>].bind-address=...
---- ----
==== ====
.`spring.data.gemfire.*` Cluster properties .`spring.data.gemfire.*` Cluster properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Default | From | Name | Description | Default | From
| `cluster.region.type` | Specifies the data management policy used when creating regions on the servers in the cluster. | {apache-geode-javadoc}/org/apache/geode/cache/RegionShortcut.html#PARTITION[`RegionShortcut.PARTITION`] | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#serverRegionShortcut--[`EnableClusterConfiguration.serverRegionShortcut`] | `cluster.Region.type` | Specifies the data management policy used when creating Regions on the servers in the cluster. | {apache-geode-javadoc}/org/apache/geode/cache/RegionShortcut.html#PARTITION[`RegionShortcut.PARTITION`] | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#serverRegionShortcut--[`EnableClusterConfiguration.serverRegionShortcut`]
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` _DiskStore_ properties .`spring.data.gemfire.*` _DiskStore_ properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Default | From | Name | Description | Default | From
| `disk.store.allow-force-compaction` | Whether to allow `DiskStore.forceCompaction()` to be called on regions that use a disk store. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableDiskStore.html#allowForceCompaction--[`EnableDiskStore.allowForceCompaction`] | `disk.store.allow-force-compaction` | Whether to allow `DiskStore.forceCompaction()` to be called on Regions that use a disk store. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableDiskStore.html#allowForceCompaction--[`EnableDiskStore.allowForceCompaction`]
| `disk.store.auto-compact` | Whether to cause the disk files to be automatically compacted. | `true` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableDiskStore.html#autoCompact--[`EnableDiskStore.autoCompact`] | `disk.store.auto-compact` | Whether to cause the disk files to be automatically compacted. | `true` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableDiskStore.html#autoCompact--[`EnableDiskStore.autoCompact`]
| `disk.store.compaction-threshold` | The threshold at which an oplog becomes compactible. | `50` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableDiskStore.html#compactionThreshold--[`EnableDiskStore.compactionThreshold`] | `disk.store.compaction-threshold` | The threshold at which an oplog becomes compactible. | `50` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableDiskStore.html#compactionThreshold--[`EnableDiskStore.compactionThreshold`]
| `disk.store.directory.location` | The system directory where the `DiskStore` (oplog) files are stored. | `[]` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableDiskStore.html#diskDirectories--[`EnableDiskStore.diskDirectories.location`] | `disk.store.directory.location` | The system directory where the `DiskStore` (oplog) files are stored. | `[]` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableDiskStore.html#diskDirectories--[`EnableDiskStore.diskDirectories.location`]
@@ -165,8 +161,8 @@ spring.data.gemfire.disk.store.Example.directory[1].size=8192000
==== ====
Both the name and array index are optional, and you can use any combination of name and array index. Without a name, Both the name and array index are optional, and you can use any combination of name and array index. Without a name,
the properties apply to all `DiskStore` instances. Without array indexes, all named `DiskStore` files are stored in the the properties apply to all `DiskStore` instances. Without array indexes, all named `DiskStore` files are stored in
specified location and limited to the defined size. the specified location and limited to the defined size.
.`spring.data.gemfire.*` Entity properties .`spring.data.gemfire.*` Entity properties
[width="90%",options="header"] [width="90%",options="header"]
@@ -182,12 +178,11 @@ specified location and limited to the defined size.
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Default | From | Name | Description | Default | From
| `locator.host` | The IP address or hostname of the system NIC to which the embedded locator is bound to listen for connections. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLocator.html#host--[`EnableLocator.host`] | `locator.host` | The IP address or hostname of the system NIC to which the embedded Locator is bound to listen for connections. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLocator.html#host--[`EnableLocator.host`]
| locator.port | The network port to which the embedded Locator will listen for connections. | `10334` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLocator.html#port--[`EnableLocator.port`] | locator.port | The network port to which the embedded Locator will listen for connections. | `10334` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLocator.html#port--[`EnableLocator.port`]
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` Logging properties .`spring.data.gemfire.*` Logging properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -200,35 +195,32 @@ specified location and limited to the defined size.
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` Management properties .`spring.data.gemfire.*` Management properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Default | From | Name | Description | Default | From
| `management.use-http` | Whether to use the HTTP protocol to communicate with a {geode-name} manager. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#useHttp--[`EnableClusterConfiguration.useHttp`] | `management.use-http` | Whether to use the HTTP protocol to communicate with an {geode-name} Manager. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#useHttp--[`EnableClusterConfiguration.useHttp`]
| `management.http.host` | The IP address or hostname of the {geode-name} ranager that runs the HTTP service. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#host--[`EnableClusterConfiguration.host`] | `management.http.host` | The IP address or hostname of the {geode-name} Manager that runs the HTTP service. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#host--[`EnableClusterConfiguration.host`]
| `management.http.port` | Configures the port used by the {geode-name} Manager's HTTP service to listen for connections. | `7070` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#port--[`EnableClusterConfiguration.port`] | `management.http.port` | The port used by the {geode-name} Manager's HTTP service to listen for connections. | `7070` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#port--[`EnableClusterConfiguration.port`]
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` Manager properties
.`spring.data.gemfire.*` manager properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Default | From | Name | Description | Default | From
| `manager.access-file` | The access control list (ACL) file used by the manager to restrict access to the JMX MBeans by the clients. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#accessFile--[`EnableManager.accessFile`] | `manager.access-file` | The access control list (ACL) file used by the Manager to restrict access to the JMX MBeans by the clients. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#accessFile--[`EnableManager.accessFile`]
| manager.bind-address | The IP address or hostname of the system NIC used by the manager to bind and listen for JMX client connections. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#bindAddress--[`EnableManager.bindAddress`] | manager.bind-address | The IP address or hostname of the system NIC used by the Manager to bind and listen for JMX client connections. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#bindAddress--[`EnableManager.bindAddress`]
| `manager.hostname-for-clients` | The hostname given to JMX clients to ask the locator for the location of the manager. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#hostnameForClients--[`EnableManager.hostNameForClients`] | `manager.hostname-for-clients` | The hostname given to JMX clients to ask the Locator for the location of the Manager. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#hostnameForClients--[`EnableManager.hostNameForClients`]
| `manager.password-file` | By default, the JMX Manager lets clients without credentials connect. If this property is set to the name of a file, only clients that connect with credentials that match an entry in this file are allowed. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#passwordFile--[`EnableManager.passwordFile`] | `manager.password-file` | By default, the JMX Manager lets clients without credentials connect. If this property is set to the name of a file, only clients that connect with credentials that match an entry in this file are allowed. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#passwordFile--[`EnableManager.passwordFile`]
| `manager.port` | The port used by the manager to listen for JMX client connections. | `1099` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#port--[`EnableManager.port`] | `manager.port` | The port used by the Manager to listen for JMX client connections. | `1099` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#port--[`EnableManager.port`]
| `manager.start` | Whether to start the manager service at runtime. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#start--[`EnableManager.start`] | `manager.start` | Whether to start the Manager service at runtime. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#start--[`EnableManager.start`]
| `manager.update-rate` | The rate, in milliseconds, at which this member pushes updates to any JMX Managers. | `2000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#updateRate--[`EnableManager.updateRate`] | `manager.update-rate` | The rate, in milliseconds, at which this member pushes updates to any JMX Managers. | `2000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html#updateRate--[`EnableManager.updateRate`]
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` PDX properties .`spring.data.gemfire.*` PDX properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -237,42 +229,40 @@ specified location and limited to the defined size.
| `pdx.disk-store-name` | The name of the `DiskStore` used to store PDX type metadata to disk when PDX is persistent. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#diskStoreName--[`EnablePdx.diskStoreName`] | `pdx.disk-store-name` | The name of the `DiskStore` used to store PDX type metadata to disk when PDX is persistent. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#diskStoreName--[`EnablePdx.diskStoreName`]
| `pdx.ignore-unread-fields` | Whether PDX ignores fields that were unread during deserialization. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#ignoreUnreadFields--[`EnablePdx.ignoreUnreadFields`] | `pdx.ignore-unread-fields` | Whether PDX ignores fields that were unread during deserialization. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#ignoreUnreadFields--[`EnablePdx.ignoreUnreadFields`]
| `pdx.persistent` | Whether PDX persists type metadata to disk. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#persistent--[`EnablePdx.persistent`] | `pdx.persistent` | Whether PDX persists type metadata to disk. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#persistent--[`EnablePdx.persistent`]
| `pdx.read-serialized` | Whether a region entry is returned as a `PdxInstance` or deserialized back into object form on read. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#readSerialized--[`EnablePdx.readSerialized`] | `pdx.read-serialized` | Whether a Region entry is returned as a `PdxInstance` or deserialized back into object form on read. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#readSerialized--[`EnablePdx.readSerialized`]
| `pdx.serialize-bean-name` | The name of a custom Spring bean that implements `org.apache.geode.pdx.PdxSerializer`. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#serializerBeanName--[`EnablePdx.serializerBeanName`] | `pdx.serialize-bean-name` | The name of a custom Spring bean that implements `org.apache.geode.pdx.PdxSerializer`. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePdx.html#serializerBeanName--[`EnablePdx.serializerBeanName`]
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` Pool properties .`spring.data.gemfire.*` Pool properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
| Name | Description | Default | From | Name | Description | Default | From
| `pool.free-connection-timeout` | The timeout used to acquire a free connection from a pool. | `10000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#freeConnectionTimeout--[`EnablePool.freeConnectionTimeout`] | `pool.free-connection-timeout` | The timeout used to acquire a free connection from a Pool. | `10000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#freeConnectionTimeout--[`EnablePool.freeConnectionTimeout`]
| `pool.idle-timeout` | The amount of time a connection can be idle before expiring (and closing) the connection. | `5000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#idleTimeout--[`EnablePool.idleTimeout`] | `pool.idle-timeout` | The amount of time a connection can be idle before expiring (and closing) the connection. | `5000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#idleTimeout--[`EnablePool.idleTimeout`]
| `pool.load-conditioning-interval` | The interval for how frequently the pool checks to see if a connection to a given server should be moved to a different server to improve the load balance. | `300000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#loadConditioningInterval--[`EnablePool.loadConditioningInterval`] | `pool.load-conditioning-interval` | The interval for how frequently the Pool checks to see if a connection to a given server should be moved to a different server to improve the load balance. | `300000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#loadConditioningInterval--[`EnablePool.loadConditioningInterval`]
| `pool.locators` | Comma-delimited list of locator endpoints in the format of `locator1[port1],...,locatorN[portN]` | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#locators--[`EnablePool.locators`] | `pool.locators` | Comma-delimited list of locator endpoints in the format of `locator1[port1],...,locatorN[portN]` | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#locators--[`EnablePool.locators`]
| `pool.max-connections` | The maximum number of client to server connections that a Pool will create. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#maxConnections--[EnablePool.maxConnections] | `pool.max-connections` | The maximum number of client to server connections that a Pool will create. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#maxConnections--[EnablePool.maxConnections]
| `pool.min-connections` | The minimum number of client to server connections that a pool maintains. | `1` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#minConnections--[`EnablePool.minConnections`] | `pool.min-connections` | The minimum number of client to server connections that a Pool maintains. | `1` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#minConnections--[`EnablePool.minConnections`]
| `pool.multi-user-authentication` | Whether the created pool can be used by multiple authenticated users. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#multiUserAuthentication--[`EnablePool.multiUserAuthentication`] | `pool.multi-user-authentication` | Whether the created Pool can be used by multiple authenticated users. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#multiUserAuthentication--[`EnablePool.multiUserAuthentication`]
| `pool.ping-interval` | How often to ping servers to verify that they are still alive. | `10000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#pingInterval--[`EnablePool.pingInterval`] | `pool.ping-interval` | How often to ping servers to verify that they are still alive. | `10000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#pingInterval--[`EnablePool.pingInterval`]
| `pool.pr-single-hop-enabled` | Whether to perform single-hop data access operations between the client and servers. When `true`, the client is aware of the location of partitions on servers that host regions with `DataPolicy.PARTITION`. | `true` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#prSingleHopEnabled--[`EnablePool.prSingleHopEnabled`] | `pool.pr-single-hop-enabled` | Whether to perform single-hop data access operations between the client and servers. When `true`, the client is aware of the location of partitions on servers that host Regions with `DataPolicy.PARTITION`. | `true` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#prSingleHopEnabled--[`EnablePool.prSingleHopEnabled`]
| `pool.read-timeout` | The number of milliseconds to wait for a response from a server before timing out the operation and trying another server (if any are available). | `10000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#readTimeout--[`EnablePool.readTimeout`] | `pool.read-timeout` | The number of milliseconds to wait for a response from a server before timing out the operation and trying another server (if any are available). | `10000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#readTimeout--[`EnablePool.readTimeout`]
| `pool.ready-for-events` | Whether to signal the server that the client is prepared and ready to receive events. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#readyForEvents--[`ClientCacheApplication.readyForEvents`] | `pool.ready-for-events` | Whether to signal the server that the client is prepared and ready to receive events. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/ClientCacheApplication.html#readyForEvents--[`ClientCacheApplication.readyForEvents`]
| `pool.retry-attempts` | The number of times to retry a request after timeout/exception. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#retryAttempts--[`EnablePool.retryAttempts`] | `pool.retry-attempts` | The number of times to retry a request after timeout/exception. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#retryAttempts--[`EnablePool.retryAttempts`]
| `pool.server-group` | The group that all servers to which a pool connects must belong. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#serverGroup--[`EnablePool.serverGroup`] | `pool.server-group` | The group that all servers to which a Pool connects must belong. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#serverGroup--[`EnablePool.serverGroup`]
| `pool.servers` | Comma-delimited list of `CacheServer` endpoints in the format of `server1[port1],...,serverN[portN]` | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#servers--[`EnablePool.servers`] | `pool.servers` | Comma-delimited list of `CacheServer` endpoints in the format of `server1[port1],...,serverN[portN]` | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#servers--[`EnablePool.servers`]
| `pool.socket-buffer-size` | The socket buffer size for each connection made in all Pools. | `32768` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#socketBufferSize--[`EnablePool.socketBufferSize`] | `pool.socket-buffer-size` | The socket buffer size for each connection made in all Pools. | `32768` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#socketBufferSize--[`EnablePool.socketBufferSize`]
| `pool.statistic-interval` | How often to send client statistics to the server. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#statisticInterval--[`EnablePool.statisticInterval`] | `pool.statistic-interval` | How often to send client statistics to the server. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#statisticInterval--[`EnablePool.statisticInterval`]
| pool.subscription-ack-interval | The interval in milliseconds to wait before sending acknowledgements to the `CacheServer` for events received from the server subscriptions. | `100` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#subscriptionAckInterval--[`EnablePool.subscriptionAckInterval`] | pool.subscription-ack-interval | The interval in milliseconds to wait before sending acknowledgements to the `CacheServer` for events received from the server subscriptions. | `100` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#subscriptionAckInterval--[`EnablePool.subscriptionAckInterval`]
| `pool.subscription-enabled` | Whether the created pool has server-to-client subscriptions enabled. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#subscriptionEnabled--[`EnablePool.subscriptionEnabled`] | `pool.subscription-enabled` | Whether the created Pool has server-to-client subscriptions enabled. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#subscriptionEnabled--[`EnablePool.subscriptionEnabled`]
| `pool.subscription-message-tracking-timeout` | The `messageTrackingTimeout` attribute, which is the time-to-live period, in milliseconds, for subscription events the client has received from the server. | `900000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#subscriptionMessageTrackingTimeout--[`EnablePool.subscriptionMessageTrackingTimeout`] | `pool.subscription-message-tracking-timeout` | The `messageTrackingTimeout` attribute, which is the time-to-live period, in milliseconds, for subscription events the client has received from the server. | `900000` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#subscriptionMessageTrackingTimeout--[`EnablePool.subscriptionMessageTrackingTimeout`]
| `pool.subscription-redundancy` | The redundancy level for all pools server-to-client subscriptions. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#subscriptionRedundancy--[`EnablePool.subsriptionRedundancy`] | `pool.subscription-redundancy` | The redundancy level for all Pools server-to-client subscriptions. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#subscriptionRedundancy--[`EnablePool.subsriptionRedundancy`]
| `pool.thread-local-connections` | The thread local connections policy for all pools. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#threadLocalConnections--[`EnablePool.threadLocalConnections`] | `pool.thread-local-connections` | The thread local connections policy for all Pools. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnablePool.html#threadLocalConnections--[`EnablePool.threadLocalConnections`]
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` Security properties .`spring.data.gemfire.*` Security properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -284,20 +274,19 @@ specified location and limited to the defined size.
| `security.client.accessor` | X | X | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#clientAccessor--[`EnableAuth.clientAccessor`] | `security.client.accessor` | X | X | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#clientAccessor--[`EnableAuth.clientAccessor`]
| `security.client.accessor-post-processor` | The callback that should be invoked in the post-operation phase, which is when the operation has completed on the server but before the result is sent to the client. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#clientAccessorPostProcessor--[`EnableAuth.clientAccessorPostProcessor`] | `security.client.accessor-post-processor` | The callback that should be invoked in the post-operation phase, which is when the operation has completed on the server but before the result is sent to the client. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#clientAccessorPostProcessor--[`EnableAuth.clientAccessorPostProcessor`]
| `security.client.authentication-initializer` | Static creation method that returns an `AuthInitialize` object, which obtains credentials for peers in a cluster. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#clientAuthenticationInitializer--[`EnableSecurity.clientAuthentiationInitializer`] | `security.client.authentication-initializer` | Static creation method that returns an `AuthInitialize` object, which obtains credentials for peers in a cluster. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#clientAuthenticationInitializer--[`EnableSecurity.clientAuthentiationInitializer`]
| `security.client.authenticator` | Static creation method that returns an authenticator object used by a cluster member (locator or server) to verify the credentials of a connecting client. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#clientAuthenticator--[`EnableAuth.clientAuthenticator`] | `security.client.authenticator` | Static creation method that returns an `Authenticator` object used by a cluster member (Locator or Server) to verify the credentials of a connecting client. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#clientAuthenticator--[`EnableAuth.clientAuthenticator`]
| `security.client.diffie-hellman-algorithm` | Used for authentication. For secure transmission of sensitive credentials (such as passwords), you can encrypt the credentials by using the Diffie-Hellman key-exchange algorithm. You can do so by setting the `security-client-dhalgo` system property on the clients to the name of a valid, symmetric key cipher supported by the JDK. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#clientDiffieHellmanAlgorithm--[`EnableAuth.clientDiffieHellmanAlgorithm`] | `security.client.diffie-hellman-algorithm` | Used for authentication. For secure transmission of sensitive credentials (such as passwords), you can encrypt the credentials by using the Diffie-Hellman key-exchange algorithm. You can do so by setting the `security-client-dhalgo` system property on the clients to the name of a valid, symmetric key cipher supported by the JDK. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#clientDiffieHellmanAlgorithm--[`EnableAuth.clientDiffieHellmanAlgorithm`]
| `security.log.file` | The pathname to a log file used for security log messages. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#securityLogFile--[`EnableAuth.securityLogFile`] | `security.log.file` | The pathname to a log file used for security log messages. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#securityLogFile--[`EnableAuth.securityLogFile`]
| `security.log.level` | The log level for security log messages. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#securityLogLevel--[`EnableAuth.securityLogLevel`] | `security.log.level` | The log level for security log messages. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#securityLogLevel--[`EnableAuth.securityLogLevel`]
| `security.manager.class-name` | The name of a class that implements `org.apache.geode.security.SecurityManager`. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#securityManagerClassName--[`EnableSecurity.securityManagerClassName`] | `security.manager.class-name` | The name of a class that implements `org.apache.geode.security.SecurityManager`. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#securityManagerClassName--[`EnableSecurity.securityManagerClassName`]
| `security.peer.authentication-initializer` | Static creation method that returns an `AuthInitialize` object, which obtains credentials for peers in a cluster. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#peerAuthenticationInitializer--[`EnableSecurity.peerAuthenticationInitializer`] | `security.peer.authentication-initializer` | Static creation method that returns an `AuthInitialize` object, which obtains credentials for peers in a cluster. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#peerAuthenticationInitializer--[`EnableSecurity.peerAuthenticationInitializer`]
| `security.peer.authenticator` | Static creation method that returns an authenticator object, which is used by a peer to verify the credentials of a connecting node. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#peerAuthenticator--[`EnableAuth.peerAuthenticator`] | `security.peer.authenticator` | Static creation method that returns an `Authenticator` object, which is used by a peer to verify the credentials of a connecting node. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#peerAuthenticator--[`EnableAuth.peerAuthenticator`]
| security.peer.verify-member-timeout | The timeout in milliseconds used by a peer to verify membership of an unknown authenticated peer requesting a secure connection. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#peerVerifyMemberTimeout--[`EnableAuth.peerVerifyMemberTimeout`] | security.peer.verify-member-timeout | The timeout in milliseconds used by a peer to verify membership of an unknown authenticated peer requesting a secure connection. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableAuth.html#peerVerifyMemberTimeout--[`EnableAuth.peerVerifyMemberTimeout`]
| `security.post-processor.class-name` | The name of a class that implements the `org.apache.geode.security.PostProcessor` interface that can be used to change the returned results of Region get operations. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#securityPostProcessorClassName--[`EnableSecurity.securityPostProcessorClassName`] | `security.post-processor.class-name` | The name of a class that implements the `org.apache.geode.security.PostProcessor` interface that can be used to change the returned results of Region get operations. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#securityPostProcessorClassName--[`EnableSecurity.securityPostProcessorClassName`]
| `security.shiro.ini-resource-path` | The {geode-name} system property that refers to the location of an Apache Shiro INI file that configures the Apache Shiro Security Framework in order to secure {geode-name}. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#shiroIniResourcePath--[`EnableSecurity.shiroIniResourcePath`] | `security.shiro.ini-resource-path` | The {geode-name} System property that refers to the location of an Apache Shiro INI file that configures the Apache Shiro Security Framework in order to secure {geode-name}. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#shiroIniResourcePath--[`EnableSecurity.shiroIniResourcePath`]
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` SSL properties .`spring.data.gemfire.*` SSL properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -306,7 +295,7 @@ specified location and limited to the defined size.
| `security.ssl.certificate.alias.cluster` | The alias to the stored SSL certificate used by the cluster to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`] | `security.ssl.certificate.alias.cluster` | The alias to the stored SSL certificate used by the cluster to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`]
| `security.ssl.certificate.alias.default-alias` | The default alias to the stored SSL certificate used to secure communications across the entire {geode-name} system. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#defaultCertificateAlias--[`EnableSsl.defaultCertificateAlias`] | `security.ssl.certificate.alias.default-alias` | The default alias to the stored SSL certificate used to secure communications across the entire {geode-name} system. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#defaultCertificateAlias--[`EnableSsl.defaultCertificateAlias`]
| `security.ssl.certificate.alias.gateway` | The alias to the stored SSL certificate used by the WAN Gateway Senders/Receivers to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`] | `security.ssl.certificate.alias.gateway` | The alias to the stored SSL certificate used by the WAN Gateway Senders/Receivers to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`]
| `security.ssl.certificate.alias.jmx` | The alias to the stored SSL certificate used by the manager's JMX-based JVM MBeanServer and JMX clients to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`] | `security.ssl.certificate.alias.jmx` | The alias to the stored SSL certificate used by the Manager's JMX-based JVM MBeanServer and JMX clients to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`]
| `security.ssl.certificate.alias.locator` | The alias to the stored SSL certificate used by the Locator to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`] | `security.ssl.certificate.alias.locator` | The alias to the stored SSL certificate used by the Locator to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`]
| `security.ssl.certificate.alias.server` | The alias to the stored SSL certificate used by clients and servers to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`] | `security.ssl.certificate.alias.server` | The alias to the stored SSL certificate used by clients and servers to secure communications. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`]
| `security.ssl.certificate.alias.web` | The alias to the stored SSL certificate used by the embedded HTTP server to secure communications (HTTPS). | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`] | `security.ssl.certificate.alias.web` | The alias to the stored SSL certificate used by the embedded HTTP server to secure communications (HTTPS). | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSsl.html#componentCertificateAliases--[`EnableSsl.componentCertificateAliases`]
@@ -324,7 +313,6 @@ specified location and limited to the defined size.
|===================================================================================================================== |=====================================================================================================================
.`spring.data.gemfire.*` Service properties .`spring.data.gemfire.*` Service properties
[width="90%",options="header"] [width="90%",options="header"]
|===================================================================================================================== |=====================================================================================================================
@@ -333,9 +321,9 @@ specified location and limited to the defined size.
| `service.http.bind-address` | The IP address or hostname of the system NIC used by the embedded HTTP server to bind and listen for HTTP(S) connections. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableHttpService.html#bindAddress--[`EnableHttpService.bindAddress`] | `service.http.bind-address` | The IP address or hostname of the system NIC used by the embedded HTTP server to bind and listen for HTTP(S) connections. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableHttpService.html#bindAddress--[`EnableHttpService.bindAddress`]
| `service.http.port` | The port used by the embedded HTTP server to listen for HTTP(S) connections. | `7070` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableHttpService.html#port--[`EnableHttpService.port`] | `service.http.port` | The port used by the embedded HTTP server to listen for HTTP(S) connections. | `7070` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableHttpService.html#port--[`EnableHttpService.port`]
| `service.http.ssl-require-authentication` | Whether two-way HTTP authentication is required. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableHttpService.html#sslRequireAuthentication--[`EnableHttpService.sslRequireAuthentication`] | `service.http.ssl-require-authentication` | Whether two-way HTTP authentication is required. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableHttpService.html#sslRequireAuthentication--[`EnableHttpService.sslRequireAuthentication`]
| `service.http.dev-rest-api-start` | Whether to start the developer REST API web service. A full installation of {geode-name} is required, and you must set the `$GEODE` environment variable. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableHttpService.html#startDeveloperRestApi--[`EnableHttpService.startDeveloperRestApi`] | `service.http.dev-rest-api-start` | Whether to start the Developer REST API web service. A full installation of {geode-name} is required, and you must set the `$GEODE` environment variable. | `false` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableHttpService.html#startDeveloperRestApi--[`EnableHttpService.startDeveloperRestApi`]
| `service.memcached.port` | The port of the embedded memcached server (service). | `11211`| {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableMemcachedServer.html#port--[`EnableMemcachedServer.port`] | `service.memcached.port` | The port of the embedded Memcached server (service). | `11211`| {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableMemcachedServer.html#port--[`EnableMemcachedServer.port`]
| `service.memcached.protocol` | The protocol used by the embedded memcached server (service). | `ASCII` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableMemcachedServer.html#protocol--[`EnableMemcachedServer.protocol`] | `service.memcached.protocol` | The protocol used by the embedded Memcached server (service). | `ASCII` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableMemcachedServer.html#protocol--[`EnableMemcachedServer.protocol`]
| `service.redis.bind-address` | The IP address or hostname of the system NIC used by the embedded Redis server to bind and listen for connections. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableRedisServer.html#bindAddress--[`EnableRedis.bindAddress`] | `service.redis.bind-address` | The IP address or hostname of the system NIC used by the embedded Redis server to bind and listen for connections. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableRedisServer.html#bindAddress--[`EnableRedis.bindAddress`]
| `service.redis.port` | The port used by the embedded Redis server to listen for connections. | `6479` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableRedisServer.html#port--[`EnableRedisServer.port`] | `service.redis.port` | The port used by the embedded Redis server to listen for connections. | `6479` | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableRedisServer.html#port--[`EnableRedisServer.port`]
@@ -345,9 +333,8 @@ specified location and limited to the defined size.
[[geode-configuration-metadata-springsession]] [[geode-configuration-metadata-springsession]]
=== Spring Session Based Properties === Spring Session Based Properties
The following properties all have a `spring.session.data.gemfire.*` prefix. For example, to set the session region The following properties all have a `spring.session.data.gemfire.*` prefix. For example, to set the session Region name,
name, set `spring.session.data.gemfire.session.region.name` in Spring Boot `application.properties`. set `spring.session.data.gemfire.session.region.name` in Spring Boot `application.properties`.
.`spring.session.data.gemfire.*` properties .`spring.session.data.gemfire.*` properties
[width="90%",options="header"] [width="90%",options="header"]
@@ -355,11 +342,11 @@ name, set `spring.session.data.gemfire.session.region.name` in Spring Boot `appl
| Name | Description | Default | From | Name | Description | Default | From
| `cache.client.pool.name` | Name of the pool used to send data access operations between the client and servers. | `gemfirePool` | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#poolName--[`EnableGemFireHttpSession.poolName`] | `cache.client.pool.name` | Name of the pool used to send data access operations between the client and servers. | `gemfirePool` | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#poolName--[`EnableGemFireHttpSession.poolName`]
| `cache.client.region.shortcut` | The `DataPolicy` used by the client region to manage (HTTP) session state. | {apache-geode-javadoc}/org/apache/geode/cache/client/ClientRegionShortcut.html#PROXY[`ClientRegionShortcut.PROXY`] | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#clientRegionShortcut--[`EnableGemFireHttpSession.clientRegionShortcut`] | `cache.client.Region.shortcut` | The `DataPolicy` used by the client Region to manage (HTTP) session state. | {apache-geode-javadoc}/org/apache/geode/cache/client/ClientRegionShortcut.html#PROXY[`ClientRegionShortcut.PROXY`] | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#clientRegionShortcut--[`EnableGemFireHttpSession.clientRegionShortcut`]
| `cache.server.region.shortcut` | The `DataPolicy` used by the server region to manage (HTTP) session state. | {apache-geode-javadoc}/org/apache/geode/cache/RegionShortcut.html#PARTITION[`RegionShortcut.PARTITION`] | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#serverRegionShortcut--[`EnableGemFireHttpSession.serverRegionShortcut`] | `cache.server.Region.shortcut` | The `DataPolicy` used by the server Region to manage (HTTP) session state. | {apache-geode-javadoc}/org/apache/geode/cache/RegionShortcut.html#PARTITION[`RegionShortcut.PARTITION`] | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#serverRegionShortcut--[`EnableGemFireHttpSession.serverRegionShortcut`]
| `session.attributes.indexable` | The names of session attributes for which an index is created. | `[]` | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#indexableSessionAttributes--[`EnableGemFireHttpSession.indexableSessionAttributes`] | `session.attributes.indexable` | The names of session attributes for which an Index is created. | `[]` | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#indexableSessionAttributes--[`EnableGemFireHttpSession.indexableSessionAttributes`]
| `session.expiration.max-inactive-interval-seconds` | Configures the number of seconds in which a session can remain inactive before it expires. | `1800` | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#maxInactiveIntervalSeconds--[`EnableGemFireHttpSession.maxInactiveIntervalSeconds`] | `session.expiration.max-inactive-interval-seconds` | Configures the number of seconds in which a session can remain inactive before it expires. | `1800` | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#maxInactiveIntervalSeconds--[`EnableGemFireHttpSession.maxInactiveIntervalSeconds`]
| `session.region.name` | The name of the (client/server) region used to manage (HTTP) session state. | `ClusteredSpringSessions` | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#regionName--[`EnableGemFireHttpSession.regionName`] | `session.Region.name` | The name of the (client/server) Region used to manage (HTTP) session state. | `ClusteredSpringSessions` | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#RegionName--[`EnableGemFireHttpSession.RegionName`]
| `session.serializer.bean-name` | The name of a Spring bean that implements `org.springframework.session.data.gemfire.serialization.SessionSerializer`. | | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#sessionSerializerBeanName--[`EnableGemFireHttpSession.sessionSerializerBeanName`] | `session.serializer.bean-name` | The name of a Spring bean that implements `org.springframework.session.data.gemfire.serialization.SessionSerializer`. | | {spring-session-data-gemfire-javadoc}/org/springframework/session/data/gemfire/config/annotation/web/http/EnableGemFireHttpSession.html#sessionSerializerBeanName--[`EnableGemFireHttpSession.sessionSerializerBeanName`]
|===================================================================================================================== |=====================================================================================================================
@@ -367,8 +354,8 @@ name, set `spring.session.data.gemfire.session.region.name` in Spring Boot `appl
[[geode-configuration-metadata-apachegeode]] [[geode-configuration-metadata-apachegeode]]
=== {geode-name} Properties === {geode-name} Properties
While we do not recommend using {geode-name} properties directly in your Spring applications, SBDG does not prevent While we do not recommend using {geode-name} properties directly in your Spring applications, SBDG does not prevent you
you from doing so. See the {apache-geode-docs}/reference/topics/gemfire_properties.html[complete reference to the {geode-name} specific properties]. from doing so. See the {apache-geode-docs}/reference/topics/gemfire_properties.html[complete reference to the {geode-name} specific properties].
WARNING: {geode-name} is very strict about the properties that may be specified in a `gemfire.properties` file. You WARNING: {geode-name} is very strict about the properties that may be specified in a `gemfire.properties` file.
cannot mix Spring properties with `gemfire.*` properties in an {geode-name} `gemfire.properties` file. You cannot mix Spring properties with `gemfire.*` properties in an {geode-name} `gemfire.properties` file.

View File

@@ -2,27 +2,28 @@
== Continuous Query == Continuous Query
:geode-name: {apache-geode-name} :geode-name: {apache-geode-name}
Some applications must process a stream of events as they happen
and intelligently react in near real-time to the countless changes in the data over time. Those applications Some applications must process a stream of events as they happen and intelligently react in (near) real-time to
need frameworks that can make processing a stream of events as they happen as easy as possible. the countless changes in the data over time. Those applications need frameworks that can make processing a stream
of events as they happen as easy as possible.
Spring Boot for {geode-name} does just that, without users having to perform any complex setup or configure any Spring Boot for {geode-name} does just that, without users having to perform any complex setup or configure any
necessary infrastructure components to enable such functionality. Developers can define the criteria for the necessary infrastructure components to enable such functionality. Developers can define the criteria for the
data in which they are interested and implement a handler to process the stream of events as they occur. data of interest and implement a handler (listener) to process the stream of events as they occur.
{apache-geode-docs}/developing/continuous_querying/chapter_overview.html[Continuous Query (CQ)] lets you {apache-geode-docs}/developing/continuous_querying/chapter_overview.html[Continuous Query (CQ)] lets you
easily define your criteria for the data you need. With CQ, you can easily define your criteria for the data you need. With CQ, you can express the criteria that match the data you need
express the criteria that match the data you need by using a query predicate. {geode-name} implements by specifying a query predicate. {geode-name} implements the
the {apache-geode-docs}/developing/querying_basics/query_basics.html[Object Query Language (OQL)] for defining {apache-geode-docs}/developing/querying_basics/query_basics.html[Object Query Language (OQL)]
and executing queries. OQL resembles SQL and supports projections, query predicates, ordering, and aggregates. for defining and executing queries. OQL resembles SQL and supports projections, query predicates, ordering,
Also, when used in CQs, they execute continuously, firing events when the data changes in such ways as to match and aggregates. Also, when used in CQs, they execute continuously, firing events when the data changes in such ways
the criteria expressed in the query predicate. as to match the criteria expressed in the query predicate.
Spring Boot for {geode-name} combines the ease of identifying the data you need by using an OQL query statement with Spring Boot for {geode-name} combines the ease of identifying the data you need by using an OQL query statement with
implementing the listener handler callback in one easy step. implementing the listener callback (handler) in one easy step.
For example, suppose we want to perform some follow-up action when a customer's financial loan application For example, suppose you want to perform some follow-up action when a customer's financial loan application is either
is either approved or denied. approved or denied.
First, the application model for our `EligibilityDecision` class might look something like the following: First, the application model for our `EligibilityDecision` class might look something like the following:
@@ -50,8 +51,8 @@ class EligibilityDecision {
---- ----
==== ====
Then we can implement and declare our CQ event handler methods to be notified when a decision Then we can implement and declare our CQ event handler methods to be notified when an eligibility decision is either
is either `APPROVED` or `DENIED`: `APPROVED` or `DENIED`:
==== ====
[source,java] [source,java]
@@ -59,7 +60,6 @@ is either `APPROVED` or `DENIED`:
@Component @Component
class EligibilityDecisionPostProcessor { class EligibilityDecisionPostProcessor {
@ContinuousQuery(name = "ApprovedDecisionsHandler", @ContinuousQuery(name = "ApprovedDecisionsHandler",
query = "SELECT decisions.* query = "SELECT decisions.*
FROM /EligibilityDecisions decisions FROM /EligibilityDecisions decisions
@@ -79,11 +79,12 @@ class EligibilityDecisionPostProcessor {
---- ----
==== ====
Thus, when eligibility is processed and a decision as been made, either approved or denied, our application Thus, when eligibility is processed and a decision has been made, either approved or denied, our application gets
gets notified, and as an application developer, you are free to code your handler and respond to the event notified, and as an application developer, you are free to code your handler and respond to the event any way you like.
any way you like. Also, because our continuous query handler class is a component (or a bean in the Spring Also, because our Continuous Query (CQ) handler class is a component (or a bean in the Spring `ApplicationContext`)
`ApplicationContext`) you can auto-wire any other beans necessary to carry out the application's intended function. you can auto-wire any other beans necessary to carry out the application's intended function.
This is not unlike Spring's {spring-framework-docs}/integration.html#jms-annotated[annotation-driven listener endpoints], This is not unlike Spring's {spring-framework-docs}/integration.html#jms-annotated[annotation-driven listener endpoints],
which are used in (JMS) message listeners and handlers, except in Spring Boot for {geode-name}, you need not do anything special which are used in (JMS) message listeners and handlers, except in Spring Boot for {geode-name}, you need not do anything
to enable this functionality. You can declare the `@ContinuousQuery` annotation on any POJO method go work on other things. special to enable this functionality. You can declare the `@ContinuousQuery` annotation on any POJO method and go to
work on other things.

View File

@@ -5,57 +5,62 @@
Anytime data is overflowed or persisted to disk, transferred between clients and servers, transferred between peers in a cluster or between Anytime data is overflowed or persisted to disk, transferred between clients and servers, transferred between peers in a cluster or between
different clusters in a multi-site topology, all data stored in {geode-name} must be serializable. different clusters in a multi-site topology, all data stored in {geode-name} must be serializable.
To serialize objects in Java, object types must implement the `java.io.Serializable` interface. However, if you have Anytime data is overflowed or persisted to disk, transferred between clients and servers, transferred between peers
a large number of application domain object types that currently do not implement `java.io.Serializable`, in a cluster or between different clusters in a multi-site WAN topology, all data stored in {geode-name} must be
refactoring hundreds or even thousands of class types to implement `Serializable` would be a tedious task just to serializable.
store and manage those objects in {geode-name}.
Additionally, it is not only your application domain object types you necessarily need to consider. If you To serialize objects in Java, object types must implement the `java.io.Serializable` interface. However, if you have a
used third-party libraries in your application domain model, any types referred to by your application domain object types large number of application domain object types that currently do not implement `java.io.Serializable`, refactoring
stored in {geode-name} must be serializable too. This type explosion may bleed into class types for which you may have hundreds or even thousands of class types to implement `java.io.Serializable` would be a tedious task just to store
and manage those objects in {geode-name}.
Additionally, it is not only your application domain object types you necessarily need to consider. If you used
third-party libraries in your application domain model, any types referred to by your application domain object types
stored in {geode-name} must also be serializable. This type explosion may bleed into class types for which you may have
no control over. no control over.
Furthermore, Java serialization is not the most efficient format, given that metadata about your types is stored with Furthermore, Java serialization is not the most efficient format, given that metadata about your types is stored with
the data itself. Therefore, even though Java serialized bytes are more descriptive, it adds a great deal of overhead. the data itself. Therefore, even though Java serialized bytes are more descriptive, it adds a great deal of overhead.
Then, along came serialization using {geode-name}'s {apache-geode-docs}/developing/data_serialization/gemfire_pdx_serialization.html[PDX] Then, along came serialization using {geode-name}'s
format. PDX stands for Portable Data Exchange and achieves four goals: {apache-geode-docs}/developing/data_serialization/gemfire_pdx_serialization.html[PDX] format.
PDX stands for Portable Data Exchange and achieves four goals:
* Separate type metadata from the data itself, making the bytes more efficient during transfer. {geode-name} maintains * Separates type metadata from the data itself, streamlining the bytes during transfer. {geode-name} maintains a type
a type registry that stores type metadata about the objects serialized in PDX. registry that stores type metadata about the objects serialized with PDX.
* Support versioning as your application domain types evolve. It is common to have old and new applications * Supports versioning as your application domain types evolve. It is common to have old and new versions of the same
deployed to production, running simultaneously, sharing data, and possibly using different versions of the same domain application deployed to production, running simultaneously, sharing data, and possibly using different versions of the
types. PDX lets fields be added or removed while still preserving interoperability between old and new application same domain types. PDX lets fields be added or removed while still preserving interoperability between old and new
clients without loss of data. application clients without loss of data.
* Enable objects stored as PDX bytes to be queried without being de-serialized. Constant serialization and deserialization of data * Enables objects stored as PDX to be queried without being de-serialized. Constant serialization and deserialization of
is a resource-intensive task that adds to the latency of each data request when redundancy is enabled. Since data must be data is a resource-intensive task that adds to the latency of each data request when redundancy is enabled. Since data
replicated across peers in the cluster to preserve High Availability (HA) and must be serialized to be transferred, keeping is replicated across peers in the cluster to preserve High Availability (HA) and must be serialized to be transferred,
data serialized is more efficient when data is updated frequently, since it likely needs to be transferred again keeping data serialized is more efficient when data is updated frequently, since it is likely the data will need to be
to maintain consistency in the face of redundancy and availability. transferred again in order to maintain consistency in the face of redundancy and availability.
* Enable interoperability between native language clients (such as C,C++, and C#) and Java language clients, with each * Enables interoperability between native language clients (such as C, C++ and C#) and Java language clients, with each
being able to access the same data set regardless from where the data originated. being able to access the same data set regardless from where the data originated.
However, PDX does have limitations. However, PDX does have limitations.
For instance, unlike Java serialization, PDX does not handle cyclic dependencies. Therefore, you must be careful For instance, unlike Java serialization, PDX does not handle cyclic dependencies. Therefore, you must be careful how you
how you structure and design your application domain object types. structure and design your application domain object types.
Also, PDX cannot handle field type changes. Also, PDX cannot handle field type changes.
Furthermore, while {geode-name}'s general {apache-geode-docs}/developing/data_serialization/gemfire_data_serialization.html[data serialization] Furthermore, while {geode-name}'s general {apache-geode-docs}/developing/data_serialization/gemfire_data_serialization.html[Data Serialization]
handles {apache-geode-docs}/developing/delta_propagation/chapter_overview.html[deltas], this is not achievable without handles {apache-geode-docs}/developing/delta_propagation/chapter_overview.html[Deltas], this is not achievable without
de-serializing the object bytes, since it involves a method invocation, which defeats one of the key benefits of PDX: de-serializing the object, since it involves a method invocation, which defeats one of the key benefits of PDX:
preserving format to avoid the cost of serialization and deserialization. preserving format to avoid the cost of serialization and deserialization.
However, we think the benefits of using PDX greatly outweigh the limitations and, therefore, have enabled PDX by default However, we think the benefits of using PDX outweigh the limitations and, therefore, have enabled PDX by default.
when using Spring Boot for {geode-name}.
You need do nothing special. You can code your types and rest assured that objects of those types are You need do nothing special. You can code your domain types and rest assured that objects of those domain types are
properly serialized when overflowed and persisted to disk, transferred between clients and servers, transferred between peers in a cluster, properly serialized when overflowed and persisted to disk, transferred between clients and servers, transferred between
and even when data is transferred over the WAN when you use {geode-name}'s multi-site topology. peers in a cluster, and even when data is transferred over the network when you use {geode-name}'s multi-site WAN
topology.
.EligibilityDecision is automatically serialiable without implementing Java Serializable. .EligibilityDecision is automatically serialiable without implementing Java Serializable.
==== ====
@@ -74,44 +79,47 @@ Java Serialization format.
=== SDG `MappingPdxSerializer` vs. {geode-name}'s `ReflectionBasedAutoSerializer` === SDG `MappingPdxSerializer` vs. {geode-name}'s `ReflectionBasedAutoSerializer`
Under-the-hood, Spring Boot for {geode-name} {spring-data-geode-docs-html}/#bootstrap-annotation-config-pdx[enables] Under-the-hood, Spring Boot for {geode-name} {spring-data-geode-docs-html}/#bootstrap-annotation-config-pdx[enables]
and uses Spring Data for {geode-name}'s {spring-data-geode-javadoc}/org/springframework/data/gemfire/mapping/MappingPdxSerializer.html[`MappingPdxSerializer`] and uses Spring Data for {geode-name}'s
to serialize your application domain objects by using PDX. {spring-data-geode-javadoc}/org/springframework/data/gemfire/mapping/MappingPdxSerializer.html[`MappingPdxSerializer`]
to serialize your application domain objects with PDX.
TIP: See the SDG {spring-data-geode-docs-html}/#mapping.pdx-serializer[Reference Guide] for more details TIP: See the SDG {spring-data-geode-docs-html}/#mapping.pdx-serializer[Reference Guide] for more details
on the `MappingPdxSerializer` class. on the `MappingPdxSerializer` class.
The `MappingPdxSerializer` offers several advantages above and beyond {geode-name}'s own The `MappingPdxSerializer` class offers several advantages above and beyond {geode-name}'s own
{apache-geode-javadoc}/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[`ReflectionBasedAutoSerializer`] class. {apache-geode-javadoc}/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[`ReflectionBasedAutoSerializer`] class.
TIP: See {geode-name}'s {apache-geode-docs}/developing/data_serialization/auto_serialization.html[User Guide] TIP: See {geode-name}'s {apache-geode-docs}/developing/data_serialization/auto_serialization.html[User Guide]
for more details about the `ReflectionBasedAutoSerializer`. for more details about the `ReflectionBasedAutoSerializer`.
The SDG `MappingPdxSerializer` offers the following benefits and capabilities: The SDG `MappingPdxSerializer` class offers the following benefits and capabilities:
* PDX serialization is based on Spring Data's powerful mapping infrastructure and meta-data. * PDX serialization is based on Spring Data's powerful mapping infrastructure and metadata.
* Includes support for both `includes` and `excludes` with {spring-data-geode-docs-html}/#mapping.pdx-serializer.type-filtering[type filtering]. * Includes support for both `includes` and `excludes` with first-class
{spring-data-geode-docs-html}/#mapping.pdx-serializer.type-filtering[type filtering].
Additionally, you can implement type filters by using Java's `java.util.function.Predicate` interface as opposed to Additionally, you can implement type filters by using Java's `java.util.function.Predicate` interface as opposed to
the limited regex capabilities provided by {geode-name}'s `ReflectionBasedAutoSerializer` class. By default, the limited regex capabilities provided by {geode-name}'s `ReflectionBasedAutoSerializer` class. By default,
`MappingPdxSerializer` excludes all types in the following packages: `java`, `org.apache.geode`, `org.springframework` `MappingPdxSerializer` excludes all types in the following packages: `java`, `org.apache.geode`, `org.springframework`
and `com.gemstone.gemfire`. and `com.gemstone.gemfire`.
* Handles {spring-data-geode-docs-html}/#mapping.pdx-serializer.transient-properties[transient object fields and properties] * Handles {spring-data-geode-docs-html}/#mapping.pdx-serializer.transient-properties[transient object fields
when either Java's `transient` keyword or Spring Data's `@Transient` annotation is used. and properties] when either Java's `transient` keyword or Spring Data's `@Transient` annotation is used.
* Handles {spring-data-geode-docs-html}/#mapping.pdx-serializer.read-only-properties[read-only object properties]. * Handles {spring-data-geode-docs-html}/#mapping.pdx-serializer.read-only-properties[read-only object properties].
* Automatically determines the identifier of your entities when you annotate the appropriate entity field or property * Automatically determines the identifier of your entities when you annotate the appropriate entity field or property
with Spring Data's {spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`@Id`] annotation. with Spring Data's {spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`@Id`] annotation.
* Lets `o.a.g.pdx.PdxSerializers` be registered to {spring-data-geode-docs-html}/#mapping.pdx-serializer.custom-serialization[customize the serialization] * Lets additional `o.a.g.pdx.PdxSerializers` be registered to
of nested entity field and property types. {spring-data-geode-docs-html}/#mapping.pdx-serializer.custom-serialization[customize the serialization]
of nested entity/object field and property types.
The support for `includes` and `excludes` deserves special attention, since the `MappingPdxSerializer` "`excludes`" all Java, Spring, and {geode-name} The support for `includes` and `excludes` deserves special attention, since the `MappingPdxSerializer` excludes all Java,
types, by default. However,, what happens when you need to serialize one of those types? Spring, and {geode-name} types, by default. However, what happens when you need to serialize one of those types?
For example, suppose you need to be able to serialize objects of type `java.security.Principal`. Then you can For example, suppose you need to serialize objects of type `java.security.Principal`. Then you can override the excludes
override the excludes by registering an "`include`" type filter: by registering an `include` type filter:
==== ====
[source,java] [source,java]
@@ -143,5 +151,5 @@ class SpringBootApacheGeodeClientCacheApplication {
---- ----
==== ====
TIP: Normally, you need not explicitly declare SDG's `@EnablePdx` annotation to enable and configure PDX. TIP: Normally, you need not explicitly declare SDG's `@EnablePdx` annotation to enable and configure PDX. However,
However, if you want to override auto-configuration, as we have demonstrated above, you must do this. if you want to override auto-configuration, as we have demonstrated above, you must do this.

View File

@@ -5,7 +5,8 @@
One of the most important tasks during development is ensuring your Spring Boot application handles data correctly. One of the most important tasks during development is ensuring your Spring Boot application handles data correctly.
To verify the accuracy, integrity, and availability of your data, your application needs data with which to work. To verify the accuracy, integrity, and availability of your data, your application needs data with which to work.
For those already familiar with Spring Boot's support for {spring-boot-docs-html}/howto.html#howto-initialize-a-database-using-spring-jdbc[SQL database initialization], For those of you already familiar with Spring Boot's support for
{spring-boot-docs-html}/howto.html#howto-initialize-a-database-using-spring-jdbc[SQL database initialization],
the approach when using {geode-name} should be easy to understand. the approach when using {geode-name} should be easy to understand.
{geode-name} provides built-in support, similar in function to Spring Boot's SQL database initialization, by using: {geode-name} provides built-in support, similar in function to Spring Boot's SQL database initialization, by using:
@@ -14,36 +15,39 @@ the approach when using {geode-name} should be easy to understand.
* {apache-geode-docs}/managing/cache_snapshots/chapter_overview.html[Snapshot service] * {apache-geode-docs}/managing/cache_snapshots/chapter_overview.html[Snapshot service]
* {apache-geode-docs}/developing/storing_data_on_disk/chapter_overview.html[Persistence] with {apache-geode-docs}/managing/disk_storage/chapter_overview.html[disk storage] * {apache-geode-docs}/developing/storing_data_on_disk/chapter_overview.html[Persistence] with {apache-geode-docs}/managing/disk_storage/chapter_overview.html[disk storage]
For example, by enabling persistence with disk storage, you could {apache-geode-docs}/managing/disk_storage/backup_restore_disk_store.html[backup and restore] For example, by enabling persistence with disk storage, you could
{apache-geode-docs}/managing/disk_storage/backup_restore_disk_store.html[backup and restore]
persistent `DiskStore` files from one cluster to another. persistent `DiskStore` files from one cluster to another.
Alternatively, using {geode-name}'s snapshot service, you can export data contained in targeted `Regions` from one Alternatively, using {geode-name}'s Snapshot Service, you can export data contained in targeted `Regions` from one
cluster during shutdown and import the data into another cluster on startup. The snapshot service lets you filter cluster during shutdown and import the data into another cluster on startup. The Snapshot Service lets you filter data
data while it is being imported and exported. while it is being imported and exported.
Finally, you can use {geode-name} shell (Gfsh) commands to {spring-data-geode-docs-html}/tools_modules/gfsh/command-pages/export.html#topic_263B70069BFC4A7185F86B3272011734[export data] Finally, you can use {geode-name} shell (Gfsh) commands to
{spring-data-geode-docs-html}/tools_modules/gfsh/command-pages/export.html#topic_263B70069BFC4A7185F86B3272011734[export data]
and {apache-geode-docs}/tools_modules/gfsh/command-pages/import.html#topic_jw2_2ld_2l[import data]. and {apache-geode-docs}/tools_modules/gfsh/command-pages/import.html#topic_jw2_2ld_2l[import data].
TIP: Spring Data for {geode-name} (SDG) contains dedicated support for {spring-data-geode-docs-html}/#bootstrap:region:persistence[persistence] TIP: Spring Data for {geode-name} (SDG) contains dedicated support for
and the {spring-data-geode-docs-html}/#bootstrap:snapshot[snapshot service]. {spring-data-geode-docs-html}/#bootstrap:region:persistence[persistence]
and the {spring-data-geode-docs-html}/#bootstrap:snapshot[Snapshot Service].
In all cases, the files generated by persistence, the snapshot service and Gfsh's `export` command are in a In all cases, the files generated by persistence, the Snapshot Service and Gfsh's `export` command are in a proprietary
proprietary binary format. binary format.
Furthermore, none of these approaches are as convenient as Spring Boot's database initialization automation. Therefore, Furthermore, none of these approaches are as convenient as Spring Boot's database initialization automation. Therefore,
Spring Boot for {geode-name} (SBDG) offers support to import data from JSON into {geode-name} as PDX. Spring Boot for {geode-name} (SBDG) offers support to import data from JSON into {geode-name} as PDX.
Unlike Spring Boot, SBDG offers support for export data as well. By default, data is imported and exported in JSON format. Unlike Spring Boot, SBDG offers support to export data as well. By default, data is imported and exported in JSON format.
NOTE: SBDG does not provide an equivalent to Spring Boot's `schema.sql` file. The best way to define the data structures NOTE: SBDG does not provide an equivalent to Spring Boot's `schema.sql` file. The best way to define the data structures
(the `Region` instances) that manage your data is with SDG's annotation-based configuration support for defining cache `Region` instances (the `Region` instances) that manage your data is with SDG's annotation-based configuration support for defining cache
from your application's {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[entity classes] or indirectly `Region` instances from your application's {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[entity classes]
from Spring and JSR-107 or JCache {spring-data-geode-docs-html}/#bootstrap-annotation-config-caching[caching annotations]. or indirectly from Spring and JSR-107 or JCache {spring-data-geode-docs-html}/#bootstrap-annotation-config-caching[caching annotations].
TIP: See SBDG's <<geode-configuration-declarative-annotations-productivity-regions,documentation>> on the same. TIP: See SBDG's <<geode-configuration-declarative-annotations-productivity-regions,documentation>> on the same.
WARNING: While this feature works and many edge cases were thought through and tested thoroughly, there are still WARNING: While this feature works and many edge cases were thought through and tested thoroughly, there are still some
some limitations that need to be ironed out. See https://github.com/spring-projects/spring-boot-data-geode/issues/82[issue-82] limitations that need to be ironed out. See https://github.com/spring-projects/spring-boot-data-geode/issues/82[issue-82]
and https://github.com/spring-projects/spring-boot-data-geode/issues/83[issue-83] for more details. The Spring team and https://github.com/spring-projects/spring-boot-data-geode/issues/83[issue-83] for more details. The Spring team
strongly recommends that this feature be used only for development and testing purposes. strongly recommends that this feature be used only for development and testing purposes.
@@ -51,21 +55,21 @@ strongly recommends that this feature be used only for development and testing p
=== Importing Data === Importing Data
You can import data into a `Region` by defining a JSON file that contain the JSON objects you wish to load. The JSON You can import data into a `Region` by defining a JSON file that contain the JSON objects you wish to load. The JSON
file must follow the following naming convention and be placed in the root of your application classpath: file must follow a predefined naming convention and be placed in the root of your application classpath:
`data-<regionName>.json` `data-<regionName>.json`
NOTE: `<regionName>` refers to the lowercase "`name`" of the `Region`, as defined by NOTE: `<regionName>` refers to the lowercase "name" of the `Region`, as defined by
{apache-geode-javadoc}/org/apache/geode/cache/Region.html#getName--[`Region.getName()`]. {apache-geode-javadoc}/org/apache/geode/cache/Region.html#getName--[`Region.getName()`].
For example, if you have a `Region` named `Orders`, you would create a JSON file called `data-orders.json` For example, if you have a `Region` named "Orders", you would create a JSON file called `data-orders.json` and place it
and place it in the root of your application classpath (for example, in `src/test/resources`). in the root of your application classpath (for example, in `src/test/resources`).
Create JSON files for each `Region` that is implicitly defined (for example, by using `@EnableEntityDefinedRegions`) or explicitly Create JSON files for each `Region` that is implicitly defined (for example, by using `@EnableEntityDefinedRegions`)
defined (with `ClientRegionFactoryBean` in Java configuration) in your Spring Boot application configuration that you or explicitly defined (with `ClientRegionFactoryBean` in Java configuration) in your Spring Boot application
want to load with data. configuration that you want to load with data.
The JSON file that contains JSON data for `Orders` might appear as follows: The JSON file that contains JSON data for the "Orders" `Region` might appear as follows:
.`data-orders.json` .`data-orders.json`
==== ====
@@ -115,9 +119,10 @@ The JSON file that contains JSON data for `Orders` might appear as follows:
---- ----
==== ====
The application entity classes that matches the JSON data might look something like the following listing: The application entity classes that matches the JSON data from the JSON file might look something like the following
listing:
.Point-of-Sale (POS) Application Model Classes .Point-of-Sale (POS) Application Domain Model Classes
==== ====
[source,java] [source,java]
---- ----
@@ -149,13 +154,14 @@ class Product {
---- ----
==== ====
As the preceding listings show, the object model and corresponding JSON can be arbitrarily complex with a hierarchy of objects As the preceding listings show, the object model and corresponding JSON can be arbitrarily complex with a hierarchy of
that have complex types. objects that have complex types.
[[geode-data-using-import-metadata]] [[geode-data-using-import-metadata]]
==== JSON metadata ==== JSON metadata
We want to draw your attention to a few other details contained in the object model and JSON shown <<geode-data-using-import,earlier>>. We want to draw your attention to a few other details contained in the object model and JSON shown
<<geode-data-using-import,earlier>>.
[[geode-data-using-import-metadata-attype]] [[geode-data-using-import-metadata-attype]]
===== The `@type` metadata field ===== The `@type` metadata field
@@ -195,22 +201,24 @@ to which the JSON object maps. Otherwise, the `PdxInstance.getObject()` method w
It is possible for {geode-name}'s PDX serialization framework to return a `PurchaseOrder` from `Region.get(key)` as well, It is possible for {geode-name}'s PDX serialization framework to return a `PurchaseOrder` from `Region.get(key)` as well,
but it depends on the value of PDX's `read-serialized`, cache-level configuration setting, among other factors. but it depends on the value of PDX's `read-serialized`, cache-level configuration setting, among other factors.
NOTE: When JSON is imported into a `Region` as PDX, the {apache-geode-javadoc}/org/apache/geode/pdx/PdxInstance.html#getClassName--[`PdxInstance.getClassName()`] NOTE: When JSON is imported into a `Region` as PDX, the
does not refer to a valid Java class. It is {apache-geode-javadoc}/org/apache/geode/pdx/JSONFormatter.html#JSON_CLASSNAME[`JSONFormatter.JSON_CLASSNAME`]. {apache-geode-javadoc}/org/apache/geode/pdx/PdxInstance.html#getClassName--[`PdxInstance.getClassName()`]
does not refer to a valid Java class. It is
{apache-geode-javadoc}/org/apache/geode/pdx/JSONFormatter.html#JSON_CLASSNAME[`JSONFormatter.JSON_CLASSNAME`].
As a result, `Region` data access operations, such as `Region.get(key)`, return a `PdxInstance` and not a Java object. As a result, `Region` data access operations, such as `Region.get(key)`, return a `PdxInstance` and not a Java object.
TIP: You may need to proxy `Region` "`read`" data access operations (such as `Region.get(key)`) by setting the SBDG property TIP: You may need to proxy `Region` read data access operations (such as `Region.get(key)`) by setting the SBDG property
`spring.boot.data.gemfire.cache.region.advice.enabled` to `true`. When this property is set, `Region` instances are proxied to `spring.boot.data.gemfire.cache.region.advice.enabled` to `true`. When this property is set, `Region` instances are
wrap a `PdxInstance` in a `PdxInstanceWrapper` to appropriately handle the `PdxInstance.getObject()` call in proxied to wrap a `PdxInstance` in a `PdxInstanceWrapper` to appropriately handle the `PdxInstance.getObject()` call
your application code. in your application code.
[[geode-data-using-import-metadata-id]] [[geode-data-using-import-metadata-id]]
===== The `id` field and the `@identifier` metadata field ===== The `id` field and the `@identifier` metadata field
The top-level objects in your JSON must have an identifier, such as an `id` field. This identifier is used as the Top-level objects in your JSON must have an identifier, such as an `id` field. This identifier is used as the identity
identity and "`key`" of the object (or `PdxInstance`) when stored in the `Region` (for example, `Region.put(key, object)`). and key of the object (or `PdxInstance`) when stored in the `Region` (for example, `Region.put(key, object)`).
You may have noticed that the JSON for the `Orders` shown earlier declared an `id` field as the identifier: You may have noticed that the JSON for the "Orders" `Region` shown earlier declared an `id` field as the identifier:
.PurchaseOrder identifier ("id") .PurchaseOrder identifier ("id")
==== ====
@@ -227,11 +235,11 @@ This follows the same convention used in Spring Data. Typically, Spring Data map
field or property annotated with {spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`@Id`]. If no field or property annotated with {spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`@Id`]. If no
field or property is annotated with `@Id`, the framework falls back to searching for a field or property named `id`. field or property is annotated with `@Id`, the framework falls back to searching for a field or property named `id`.
In Spring Data for {geode-name} (SDG), this `@Id`-annotated or `id`-named field or property is used as the identifier In Spring Data for {geode-name}, this `@Id`-annotated or `id`-named field or property is used as the identifier
and as the key for the object when storing it into a `Region`. and as the key for the object when storing it into a `Region`.
However, what happens when an object or entity does not have a surrogate ID defined? Perhaps the application domain However, what happens when an object or entity does not have a surrogate ID defined? Perhaps the application domain
model class is appropriately using "`natural`" identifiers, which is quite common in practice. model class is appropriately using natural identifiers, which is quite common in practice.
Consider a `Book` class defined as follows: Consider a `Book` class defined as follows:
@@ -265,8 +273,8 @@ format. There might not be a class definition, which would lead to a `NoClassDef
So, what then? So, what then?
In this case, SBDG lets you declare the `@identifier` JSON metadata field to inform the framework In this case, SBDG lets you declare the `@identifier` JSON metadata field to inform the framework what to use as
what to use as the identifier for the object. the identifier for the object.
Consider the following example: Consider the following example:
@@ -294,18 +302,18 @@ The `@identifier` JSON metadata field informs the framework that the `isbn` fiel
==== Conditionally Importing Data ==== Conditionally Importing Data
While the Spring team recommends that users should only use this feature when developing and testing their Spring Boot While the Spring team recommends that users should only use this feature when developing and testing their Spring Boot
applications with {geode-name}, you may occasionally use this feature in production. applications with {geode-name}, you may still occasionally use this feature in production.
You might use this feature in production to preload a (REPLICATE) Region with "`reference`" data. Reference data is You might use this feature in production to preload a (REPLICATE) Region with reference data. Reference data is largely
largely static, infrequently changing, and non-transactional. Preloading reference data is particularly useful static, infrequently changing, and non-transactional. Preloading reference data is particularly useful when you want to
when you want to "`warm`" the cache. warm the cache.
When you use this feature for development and testing purposes, you can put your `Region`-specific JSON files in When you use this feature for development and testing purposes, you can put your `Region`-specific JSON files in
`src/test/resources`. This ensures that the files are not included in your application artifact (such as a JAR or WAR) when `src/test/resources`. This ensures that the files are not included in your application artifact (such as a JAR or WAR)
deployed to production. when built and deployed to production.
However, if you must use this feature to preload data in your production environment, you can still "`conditionally`" However, if you must use this feature to preload data in your production environment, you can still conditionally load
load data from JSON. To do so, configure the `spring.boot.data.gemfire.cache.data.import.active-profiles` property set to data from JSON. To do so, configure the `spring.boot.data.gemfire.cache.data.import.active-profiles` property set to
the Spring profiles that must be active for the import to take effect. the Spring profiles that must be active for the import to take effect.
Consider the following example: Consider the following example:
@@ -320,11 +328,11 @@ spring.boot.data.gemfire.cache.data.import.active-profiles=DEV, QA
---- ----
==== ====
For import to have an effect in this example, you must specifically set the `spring.profiles.active` For import to have an effect in this example, you must specifically set the `spring.profiles.active` property to one of
property to one of the valid, `active-profiles` listed in the import property (such as `QA`). Only one needs to match. the valid, `active-profiles` listed in the import property (such as `QA`). Only one needs to match.
NOTE: There are many ways to conditionally build application artifacts. You might prefer to handle this concern NOTE: There are many ways to conditionally build application artifacts. You might prefer to handle this concern in your
in your Gradle or Maven build. Gradle or Maven build.
[[geode-data-using-export]] [[geode-data-using-export]]
=== Exporting Data === Exporting Data
@@ -332,8 +340,8 @@ in your Gradle or Maven build.
Certain data stored in your application's `Regions` may be sensitive or confidential, and keeping the data secure is of Certain data stored in your application's `Regions` may be sensitive or confidential, and keeping the data secure is of
the utmost concern and priority. Therefore, exporting data is *disabled* by default. the utmost concern and priority. Therefore, exporting data is *disabled* by default.
However, if you use this feature for development and testing purposes, enabling the export capability may be However, if you use this feature for development and testing purposes, enabling the export capability may be useful to
useful to move data from one environment to another. For example, if your QA team finds a bug in the application that uses a move data from one environment to another. For example, if your QA team finds a bug in the application that uses a
particular data set, they can export the data and pass it back to the development team to import in their local particular data set, they can export the data and pass it back to the development team to import in their local
development environment to help debug the issue. development environment to help debug the issue.
@@ -354,20 +362,20 @@ SBDG is careful to export data to JSON in a format that {geode-name} expects on
WARNING: The `@identifier` metadata field is not generated automatically. While it is possible for POJOs stored in a WARNING: The `@identifier` metadata field is not generated automatically. While it is possible for POJOs stored in a
`Region` to include an `@identifier` metadata field when exported to JSON, it is not possible when the `Region` value `Region` to include an `@identifier` metadata field when exported to JSON, it is not possible when the `Region` value
is a `PdxInstance` that did not originate from JSON. In this case, you must manually ensure that the `PdxInstance` includes is a `PdxInstance` that did not originate from JSON. In this case, you must manually ensure that the `PdxInstance`
an `@identifier` metadata field before it is exported to JSON if necessary (for example, `Book.isbn`). This is only necessary includes an `@identifier` metadata field before it is exported to JSON if necessary (for example, `Book.isbn`). This is
if your entity classes do not declare an explicit identifier field, such as with the `@Id` mapping annotation, or do only necessary if your entity classes do not declare an explicit identifier field, such as with the `@Id` mapping
not have an `id` field. This scenario can also occur when inter-operating with native clients that model the application annotation, or do not have an `id` field. This scenario can also occur when inter-operating with native clients
domain objects differently and then serialize the objects by using PDX and storing them in regions on the server that are then that model the application domain objects differently and then serialize the objects by using PDX, storing them in
later consumed by your Spring Boot application. Regions on the server that are then later consumed by your Java-based, Spring Boot application.
WARNING: You may need to set the `-Dgemfire.disableShutdownHook` JVM System property to `true` before your Spring WARNING: You may need to set the `-Dgemfire.disableShutdownHook` JVM System property to `true` before your Spring
Boot application starts up when using export. Unfortunately, this Java runtime shutdown hook is registered and enabled Boot application starts up when using export. Unfortunately, this Java runtime shutdown hook is registered and enabled
in {geode-name} by default, which results in the cache and regions being closed before the SBDG Export functionality in {geode-name} by default, which results in the cache and the Regions being closed before the SBDG Export
can "`export the data`", thereby resulting in a `CacheClosedException`. SBDG functionality can export the data, thereby resulting in a `CacheClosedException`. SBDG
{github-url}/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/DataImportExportAutoConfiguration.java#L173-L183[makes a best effort] {github-url}/spring-geode-autoconfigure/src/main/java/org/springframework/geode/boot/autoconfigure/DataImportExportAutoConfiguration.java#L173-L183[makes a best effort]
to disable the {geode-name} shutdown hook when export is enabled, but it is at the mercy of the JVM `ClassLoader`, since to disable the {geode-name} JVM shutdown hook when export is enabled, but it is at the mercy of the JVM `ClassLoader`,
{geode-name}'s JVM shutdown hook since {geode-name}'s JVM shutdown hook
{apache-geode-src}/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java#L2185-L2223[registration] {apache-geode-src}/geode-core/src/main/java/org/apache/geode/distributed/internal/InternalDistributedSystem.java#L2185-L2223[registration]
is declared in a `static` initializer. is declared in a `static` initializer.
@@ -381,14 +389,14 @@ The API in SBDG for import and export functionality is separated into the follow
* Resource Reading * Resource Reading
* Resource Writing * Resource Writing
By breaking each of these functions apart into separate concerns, a developer can customize each By breaking each of these functions apart into separate concerns, a developer can customize each aspect of the import
aspect of the import and export functions. and export functions.
For example, you could import XML from the filesystem and then export JSON to a REST-based Web Service. By default, SBDG For example, you could import XML from the filesystem and then export JSON to a REST-based Web Service. By default, SBDG
imports JSON from the classpath and exports JSON to the filesystem. imports JSON from the classpath and exports JSON to the filesystem.
However, not all environments expose the filesystem, such as cloud environments like PCF. Therefore, giving users However, not all environments expose a filesystem, such as cloud environments like PCF. Therefore, giving users control
control over each aspect of the import and export processes is essential for performing the functions in any environment. over each aspect of the import and export processes is essential for performing the functions in any environment.
[[geode-data-using-import-export-api-extensions-data-format]] [[geode-data-using-import-export-api-extensions-data-format]]
==== Data Format ==== Data Format
@@ -413,8 +421,8 @@ interface CacheDataImporter extends BeanPostProcessor {
---- ----
==== ====
You can code the `importInto(..)` method to handle any data format (JSON, XML, and others) you prefer. Register a bean You can code the `importInto(:Region)` method to handle any data format (JSON, XML, and others) you prefer. Register a
that implements the `CacheDataImporter` interface in the Spring container, and the importer does its job. bean that implements the `CacheDataImporter` interface in the Spring container, and the importer does its job.
On the flip side, the primary interface to export data from a `Region` is the `CacheDataExporter`. On the flip side, the primary interface to export data from a `Region` is the `CacheDataExporter`.
@@ -435,8 +443,8 @@ interface CacheDataExporter extends DestructionAwareBeanPostProcessor {
---- ----
==== ====
You can code the `exportFrom(..)` method to handle any data format (JSON, XML, and others) you prefer. Register a bean You can code the `exportFrom(:Region)` method to handle any data format (JSON, XML, and others) you prefer. Register a
implementing the `CacheDataExporter` interface in the Spring container, and the exporter does its job. bean implementing the `CacheDataExporter` interface in the Spring container, and the exporter does its job.
For convenience, when you want to implement both import and export functionality, SBDG provides the For convenience, when you want to implement both import and export functionality, SBDG provides the
`CacheDataImporterExporter` interface, which extends both `CacheDataImporter` and `CacheDataExporter`: `CacheDataImporterExporter` interface, which extends both `CacheDataImporter` and `CacheDataExporter`:
@@ -449,7 +457,7 @@ interface CacheDataImporterExporter extends CacheDataExporter, CacheDataImporter
---- ----
==== ====
For support, SBDG also provides the `AbstractCacheDataImporterExporter` abstract base class to simplify For added support, SBDG also provides the `AbstractCacheDataImporterExporter` abstract base class to simplify
the implementation of your importer/exporter. the implementation of your importer/exporter.
[[geode-data-using-import-export-api-extensions-data-format-lifecycle-management]] [[geode-data-using-import-export-api-extensions-data-format-lifecycle-management]]
@@ -457,21 +465,22 @@ the implementation of your importer/exporter.
Sometimes, it is necessary to precisely control when data is imported or exported. Sometimes, it is necessary to precisely control when data is imported or exported.
This is especially true on import, since different `Region` instances may be collocated or tied together through a cache callback, such as This is especially true on import, since different `Region` instances may be collocated or tied together through a
`CacheListener`. In these cases, the other `Region` may need to exist before the import on the dependent `Region` cache callback, such as a `CacheListener`. In these cases, the other `Region` may need to exist before the import
proceeds, particularly if the dependencies were loosely defined. on the dependent `Region` proceeds, particularly if the dependencies were loosely defined.
Controlling the import is also important when you use SBDG's `@EnableClusterAware` annotation to Controlling the import is also important when you use SBDG's `@EnableClusterAware` annotation to push configuration
push configuration metadata from the client to the cluster in order to define server-side `Region` instances that match the metadata from the client to the cluster in order to define server-side `Region` instances that match the client-side
client-side `Region` instances, especially client `Region` instances targeted for import. The matching `Region` instances on the server side must `Region` instances, especially client `Region` instances targeted for import. The matching `Region` instances on the
exist before data is imported into client (`PROXY`) `Region` instances. server side must exist before data is imported into client (`PROXY`) `Region` instances.
In all cases, SBDG provides the `LifecycleAwareCacheDataImporterExporter` class to wrap your `CacheDataImporterExporter` In all cases, SBDG provides the `LifecycleAwareCacheDataImporterExporter` class to wrap your `CacheDataImporterExporter`
implementation. This class implements Spring's {spring-framework-javadoc}/https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/SmartLifecycle.html[`SmartLifecycle`] implementation. This class implements Spring's
{spring-framework-javadoc}/https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/SmartLifecycle.html[`SmartLifecycle`]
interface. interface.
By implementing the `SmartLifecycle` interface, you can control in which `phase` of the Spring container By implementing the `SmartLifecycle` interface, you can control in which `phase` of the Spring container the import
the import occurs. SBDG also exposes two more properties to control the lifecycle: occurs. SBDG also exposes two more properties to control the lifecycle:
.Lifecycle Management Properties .Lifecycle Management Properties
==== ====
@@ -486,9 +495,9 @@ spring.boot.data.gemfire.cache.data.import.phase=1000000
`EAGER` acts immediately, after the `Region` is initialized (the default behavior). `LAZY` delays the import until the `EAGER` acts immediately, after the `Region` is initialized (the default behavior). `LAZY` delays the import until the
`start()` method is called, which is invoked according to the `phase`, thereby ordering the import relative to the other `start()` method is called, which is invoked according to the `phase`, thereby ordering the import relative to the other
"`lifecycle-aware`" components that are registered in the Spring container. lifecycle-aware components that are registered in the Spring container.
The following example shows how to make your `CacheDataImporterExporter` "`lifecycle-aware`": The following example shows how to make your `CacheDataImporterExporter` lifecycle-aware:
==== ====
[source,java] [source,java]
@@ -534,9 +543,9 @@ interface ResourceResolver {
---- ----
==== ====
Additionally, SBDG provides the `ImportResourceResolver` and `ExportResourceResolver` marker interfaces and Additionally, SBDG provides the `ImportResourceResolver` and `ExportResourceResolver` marker interfaces and the
the `AbstractImportResourceResolver` and `AbstractExportResourceResolver` abstract base classes for implementing `AbstractImportResourceResolver` and `AbstractExportResourceResolver` abstract base classes for implementing the
the resource resolution logic used by both import and export operations. resource resolution logic used by both import and export operations.
If you wish to customize the resolution of `Resources` used for import or export, your `CacheDataImporterExporter` If you wish to customize the resolution of `Resources` used for import or export, your `CacheDataImporterExporter`
implementation can extend the `ResourceCapableCacheDataImporterExporter` abstract base class, which provides the implementation can extend the `ResourceCapableCacheDataImporterExporter` abstract base class, which provides the
@@ -544,8 +553,8 @@ aforementioned interfaces and base classes.
As stated earlier, SBDG resolves resources on import from the classpath and resources on export to the filesystem. As stated earlier, SBDG resolves resources on import from the classpath and resources on export to the filesystem.
You can customize this behavior by providing an implementation of You can customize this behavior by providing an implementation of `ImportResourceResolver`, `ExportResourceResolver`,
`ImportResourceResolver`, `ExportResourceResolver`, or both interfaces and declare instances as beans in the Spring context: or both interfaces and declare instances as beans in the Spring context:
.Import & Export ResourceResolver beans .Import & Export ResourceResolver beans
==== ====
@@ -567,8 +576,8 @@ class MyApplicationConfiguration {
---- ----
==== ====
TIP: If you need to customize the resource resolution process for each location (or `Region`) on import or export, you TIP: If you need to customize the resource resolution process for each location (or `Region`) on import or export,
can use the https://en.wikipedia.org/wiki/Composite_pattern[composite software design pattern]. you can use the https://en.wikipedia.org/wiki/Composite_pattern[Composite software design pattern].
[[geode-data-using-import-export-api-extensions-resource-resolution-default-customization]] [[geode-data-using-import-export-api-extensions-resource-resolution-default-customization]]
===== Customize Default Resource Resolution ===== Customize Default Resource Resolution
@@ -590,7 +599,7 @@ spring.boot.data.gemfire.cache.data.export.resource.location=...
The properties accept any valid resource string, as specified in the Spring The properties accept any valid resource string, as specified in the Spring
{spring-framework-docs}/core.html#resources-resourceloader[documentation] (see *Table 10. Resource strings*). {spring-framework-docs}/core.html#resources-resourceloader[documentation] (see *Table 10. Resource strings*).
This means that, even though the import defaults from the classpath, you can change the location from classpath This means that, even though import defaults from the classpath, you can change the location from classpath
to filesystem, or even network (for example, https://) by changing the prefix (or protocol). to filesystem, or even network (for example, https://) by changing the prefix (or protocol).
Import/export resource location properties can refer to other properties through property placeholders, but SBDG Import/export resource location properties can refer to other properties through property placeholders, but SBDG
@@ -618,7 +627,7 @@ SBDG populates the SpEL `EvaluationContext` with three sources of information:
* Access to the Spring `Environment` * Access to the Spring `Environment`
* Access to the current `Region` * Access to the current `Region`
Simple Java System properties or environment variables can be accessed with the follwoing expression: Simple Java System properties or environment variables can be accessed with the following expression:
==== ====
[source,text] [source,text]
@@ -627,8 +636,8 @@ Simple Java System properties or environment variables can be accessed with the
---- ----
==== ====
You can access more complex property names (including properties that use dot notation, such as the `user.home` Java System property), You can access more complex property names (including properties that use dot notation, such as the `user.home`
directly from the `Environment` by using map style syntax as follows: Java System property), directly from the `Environment` by using map style syntax as follows:
==== ====
[source,text] [source,text]
@@ -640,15 +649,16 @@ directly from the `Environment` by using map style syntax as follows:
The `#env` variable is set in the SpEL `EvaluationContext` to the Spring `Environment`. The `#env` variable is set in the SpEL `EvaluationContext` to the Spring `Environment`.
Because the SpEL `EvaluationContext` is evaluated with the Spring `ApplicationContext` as the root object, you also have Because the SpEL `EvaluationContext` is evaluated with the Spring `ApplicationContext` as the root object, you also have
access to the beans declared and registered in the Spring context and can invoke methods on them, as shown earlier with access to the beans declared and registered in the Spring container and can invoke methods on them, as shown earlier
`someBean.lookupPassword(..)`. `someBean` must be the name of the bean as declared or registered in the Spring context. with `someBean.lookupPassword(..)`. `someBean` must be the name of the bean as declared and registered in the Spring
container.
CAUTION: Be careful when accessing beans declared in the Spring context with SpEL, particularly when using `EAGER` CAUTION: Be careful when accessing beans declared in the Spring container with SpEL, particularly when using `EAGER`
import, as it may force those beans to be eagerly (or even prematurely) initialized. import, as it may force those beans to be eagerly (or even prematurely) initialized.
SBDG also sets the `#regionName` variable in the `EvaluationContext` to the name of the `Region`, SBDG also sets the `#regionName` variable in the `EvaluationContext` to the name of the `Region`, as determined by
as determined by {apache-geode-javadoc}/https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/Region.html#getName--[`Region.getName()`], {apache-geode-javadoc}/https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/Region.html#getName--[`Region.getName()`],
targeted for import/export. targeted for import and export.
This lets you not only change the location of the resource but also change the resource name (such as a filename). This lets you not only change the location of the resource but also change the resource name (such as a filename).
@@ -665,22 +675,22 @@ spring.boot.data.gemfire.cache.data.export.resource.location=\
---- ----
==== ====
NOTE: By default, the exported file is stored in the working directory (`System.getProperty("user.dir")`) of the NOTE: By default, the exported file is stored in the working directory (`System.getProperty("user.dir")`)
Spring Boot application process. of the Spring Boot application process.
TIP: See the Spring Framework {spring-framework-docs}/core.html#expressions[documentation] for more information on SpEL. TIP: See the Spring Framework {spring-framework-docs}/core.html#expressions[documentation] for more information on SpEL.
[[geode-data-using-import-export-api-extensions-resource-reading-writing]] [[geode-data-using-import-export-api-extensions-resource-reading-writing]]
==== Reading & Writing Resources ==== Reading & Writing Resources
The Spring {spring-framework-javadoc}/org/springframework/core/io/Resource.html[`Resource`] handle specifies The Spring {spring-framework-javadoc}/org/springframework/core/io/Resource.html[`Resource`] handle
the location of a resource, not how to read or write it. Even the Spring specifies tion of a resource, not how the resource is read or written. Even the Spring
{spring-framework-javadoc}/org/springframework/core/io/ResourceLoader.html[`ResourceLoader`], which is an interface for {spring-framework-javadoc}/org/springframework/core/io/ResourceLoader.html[`ResourceLoader`],
"`loading`" `Resources`, does not specifically read or write any content to the `Resource`. which is an interface for loading `Resources`, does not specifically read or write any content to the `Resource`.
SBDG separates these concerns into two interfaces: `ResourceReader` and `ResourceWriter`, respectively. SBDG separates these concerns into two interfaces: `ResourceReader` and `ResourceWriter`, respectively.
The design follows the same pattern used by Java's `InputStream/OutputStream` and `Reader/Writer` classes in The design follows the same pattern used by Java's `InputStream/OutputStream` and `Reader/Writer` classes
the `java.io` package. in the `java.io` package.
The `ResourceReader` interfaces is defined as: The `ResourceReader` interfaces is defined as:
@@ -712,17 +722,16 @@ interface ResourceWriter {
---- ----
==== ====
Both interfaces provide additional methods to compose readers and writers, much like Java's `Consumer` Both interfaces provide additional methods to compose readers and writers, much like Java's `Consumer` and `Function`
and `Function` interfaces in the `java.util.function` package. If a particular reader or writer is used in a composition interfaces in the `java.util.function` package. If a particular reader or writer is used in a composition and is unable
and is unable to handle the given `Resource`, it should throw a `UnhandledResourceException` to let the next to handle the given `Resource`, it should throw a `UnhandledResourceException` to let the next reader or writer in the
reader or writer in the composition try to read from or write to the `Resource`. composition try to read from or write to the `Resource`.
Rhe reader or writer are free to throw a `ResourceReadException` or `ResourceWriteException` to break the The reader or writer are free to throw a `ResourceReadException` or `ResourceWriteException` to break the chain of
chain of reader and writer invocations in the composition. reader and writer invocations in the composition.
To override the default export/import reader and writer used by SBDG, you can implement To override the default export/import reader and writer used by SBDG, you can implement the `ResourceReader`
the `ResourceReader` or `ResourceWriter` interfaces as appropriate and declare instances of these classes as beans or `ResourceWriter` interfaces as appropriate and declare instances of these classes as beans in the Spring container:
in the Spring context:
.Custom `ResourceReader` & `ResourceWriter` beans .Custom `ResourceReader` & `ResourceWriter` beans
==== ====

View File

@@ -9,42 +9,51 @@ The state of modern software application development is moving towards https://w
Containers offer a controlled environment to predictably build (configure and package), run, and manage your applications Containers offer a controlled environment to predictably build (configure and package), run, and manage your applications
in a reliable and repeatable manner, regardless of context. In many situations, the intrinsic benefit of using containers is obvious. in a reliable and repeatable manner, regardless of context. In many situations, the intrinsic benefit of using containers is obvious.
Understandably, {docker-site-url}[Docker's] popularity took off like wildfire, given its highly powerful and simplified The state of modern software application development is moving towards https://www.docker.com/resources/what-container[containerization].
model for creating, using, and managing containers to run packaged applications. Containers offer a controlled environment to predictably build (compile, configure and package), run, and manage your
applications in a reliable and repeatable manner, regardless of context. In many situations, the intrinsic benefit of
using containers is obvious.
Docker's ecosystem is also quite impressive, with the advent of {testcontainers-url}[testcontainers] Understandably, {docker-site-url}[Docker's] popularity took off like wildfire, given its highly powerful and simplified
and Spring Boot's now {spring-boot-docs-html}/spring-boot-features.html#building-docker-images[dedicated support] model for creating, using and managing containers to run packaged applications.
to create packaged Spring Boot apps in {docker-docs-url}/get-started/overview/#docker-objects[Docker images]
that are then later run in a Docker container. Docker's ecosystem is also quite impressive, with the advent of {testcontainers-url}[Testcontainers] and Spring Boot's
now {spring-boot-docs-html}/spring-boot-features.html#building-docker-images[dedicated support] to create packaged
Spring Boot applications in {docker-docs-url}/get-started/overview/#docker-objects[Docker images] that are then later
run in a Docker container.
TIP: See also {spring-boot-docs-html}/deployment.html#containers-deployment["`Deploying to Containers`"] to learn more. TIP: See also {spring-boot-docs-html}/deployment.html#containers-deployment["`Deploying to Containers`"] to learn more.
{geode-name} can also run in a controlled, containerized environment. The goal of this chapter {geode-name} can also run in a controlled, containerized environment. The goal of this chapter is to get you started
is to get you started running {geode-name} in a container and interfacing to a containerized {geode-name} cluster from running {geode-name} in a container and interfacing to a containerized {geode-name} cluster from your Spring Boot,
your Spring Boot, {geode-name} client applications. {geode-name} client applications.
This chapter does not cover how to run your Spring Boot, {geode-name} client applications in a container, since that is This chapter does not cover how to run your Spring Boot, {geode-name} client applications in a container, since that is
already covered by Spring Boot (again, see the Spring Boot documentation for {spring-boot-docs-html}/spring-boot-features.html#building-docker-images[Docker images] already covered by Spring Boot (again, see the Spring Boot documentation for
and {spring-boot-docs-html}/deployment.html#containers-deployment[container deployment], along with Docker's {docker-docs-url}/get-started/overview/[documentation]). {spring-boot-docs-html}/spring-boot-features.html#building-docker-images[Docker images]
and {spring-boot-docs-html}/deployment.html#containers-deployment[container deployment],
along with Docker's {docker-docs-url}/get-started/overview/[documentation]).
Instead, our focus is on how to run an {geode-name} cluster in a container and connect to it from a Spring Boot, Instead, our focus is on how to run an {geode-name} cluster in a container and connect to it from a Spring Boot,
{geode-name} client application, regardless of whether the app runs in a container or not. {geode-name} client application, regardless of whether the application runs in a container or not.
[[geode-docker-image]] [[geode-docker-image]]
=== Acquiring the {geode-name} Docker Image === Acquiring the {geode-name} Docker Image
To run an {geode-name} cluster inside a Docker container, you must first acquire the Docker image. You can get the {geode-name} To run an {geode-name} cluster inside a Docker container, you must first acquire the Docker image. You can get
Docker image from https://hub.docker.com/r/apachegeode/geode/[Docker Hub]. the {geode-name} Docker image from https://hub.docker.com/r/apachegeode/geode/[Docker Hub].
While {geode-name}'s official {apache-geode-docs}[documentation] is less than clear on how to use {geode-name} in Docker, While {geode-name}'s {apache-geode-docs}[official documentation] is less than clear on how to use {geode-name} in Docker,
we find a bit of relief in the {apache-geode-wiki}/How+to+use+Geode+on+Docker[Wiki]. However, for a complete and we find a bit of relief in the {apache-geode-wiki}/How+to+use+Geode+on+Docker[Wiki]. However, for a complete
comprehensive write up, see the instructions in the https://github.com/markito/geode-docker#building-the-container-image[README] and comprehensive write up, see the instructions in
the https://github.com/markito/geode-docker#building-the-container-image[README]
from this https://github.com/markito/geode-docker[GitHub Repo]. from this https://github.com/markito/geode-docker[GitHub Repo].
NOTE: You must have {docker-docs-url}/get-docker[Docker] installed on your local system to complete the following steps. NOTE: You must have {docker-docs-url}/get-docker[Docker] installed on your computer to complete the following steps.
Effectively, the high-level steps are as follows: Effectively, the high-level steps are as follows:
1) Acquire the {geode-name} Docker image from Docker Hub by using the `docker pull` command (shown with typical output) from the command-line: 1) Acquire the {geode-name} Docker image from Docker Hub by using the `docker pull` command (shown with typical output)
from the command-line:
.Download/Install the {geode-name} Docker Image .Download/Install the {geode-name} Docker Image
==== ====
@@ -59,11 +68,11 @@ docker.io/apachegeode/geode:latest
---- ----
==== ====
Instead of pulling from the `nightly` tag as suggested, the Spring team highly recommends that you pull from the Instead of pulling from the `nightly` tag as suggested, the Spring team highly recommends that you pull from
`latest` tag, which pulls a stable, production-ready {geode-name} Docker image based on the latest {geode-name} the `latest` tag, which pulls a stable, production-ready {geode-name} Docker image based on the latest {geode-name}
GA version. GA version.
2) Verify that the {geode-name} Docker Image was downloaded and installed successfully: 2) Verify that the {geode-name} Docker image was downloaded and installed successfully:
==== ====
[source,text] [source,text]
@@ -83,8 +92,8 @@ Now you are ready to run {geode-name} in a Docker container.
[[geode-docker-container]] [[geode-docker-container]]
=== Running {geode-name} in a Docker Container === Running {geode-name} in a Docker Container
Now that you have acquired the {geode-name} Docker image, you can run {geode-name} in a Docker container. Use the Now that you have acquired the {geode-name} Docker image, you can run {geode-name} in a Docker container.
following `docker run` command to start {geode-name} in a Docker Container: Use the following `docker run` command to start {geode-name} in a Docker container:
.Start the {geode-name} Docker Container .Start the {geode-name} Docker Container
==== ====
@@ -115,11 +124,11 @@ CONTAINER ID IMAGE COMMAND CREATED
---- ----
==== ====
We know that the {geode-name} Docker container is running since we ended up at a Gfsh command prompt in the You know that the {geode-name} Docker container is running since we ended up at a Gfsh command prompt in
interactive shell. the interactive shell.
We also mapped ports between the Docker container and the host system, exposing well-known ports used by {geode-name} We also mapped ports between the Docker container and the host system, exposing well-known ports used by {geode-name}
server-side cluster processes, such as locators and cache servers: server-side cluster processes, such as Locators and CacheServers:
.{geode-name} Ports .{geode-name} Ports
[width=30%, options="header", cols="2,1"] [width=30%, options="header", cols="2,1"]
@@ -136,15 +145,15 @@ server-side cluster processes, such as locators and cache servers:
|=== |===
It is unfortunate that the {geode-name} Docker image gives you only a Gfsh command prompt, leaving you with the task It is unfortunate that the {geode-name} Docker image gives you only a Gfsh command prompt, leaving you with the task of
of provisioning a cluster. It would have been more useful to provide preconfigured Docker images with different provisioning a cluster. It would have been more useful to provide preconfigured Docker images with different {geode-name}
{geode-name} cluster configurations, such as one Locator and one server or two locators and four servers, and so on. However, we cluster configurations, such as one Locator and one server or two Locators and four servers, and so on. However, we can
can start the cluster ourselves. start the cluster ourselves.
[[geode-docker-cluster]] [[geode-docker-cluster]]
=== Start an {geode-name} Cluster in Docker === Start an {geode-name} Cluster in Docker
From inside the {geode-name} Docker container, we can start a locator and a server: From inside the {geode-name} Docker container, we can start a Locator and a server:
.Start {geode-name} Locator & Server .Start {geode-name} Locator & Server
==== ====
@@ -226,8 +235,8 @@ Client Connections : 0
---- ----
==== ====
We now have an {geode-name} cluster running with one locator and one server inside a Docker container. We deliberately We now have an {geode-name} cluster running with one Locator and one server inside a Docker container. We deliberately
started the cluster with a minimal configuration. For example, we have no regions in which to store data: started the cluster with a minimal configuration. For example, we have no Regions in which to store data:
==== ====
[source,text] [source,text]
@@ -274,7 +283,7 @@ class Customer {
---- ----
==== ====
Also, we define a Spring Data CRUD repository to persist and access `Customers` stored in the `/Customers` region: Also, we define a Spring Data CRUD Repository to persist and access `Customers` stored in the `/Customers` Region:
.`CustomerRepository` interface .`CustomerRepository` interface
==== ====
@@ -290,21 +299,21 @@ interface CustomerRepository extends CrudRepository<Customer, Long> {
Our main class is annotated with `@SpringBootApplication`, making it be a proper Spring Boot application. Our main class is annotated with `@SpringBootApplication`, making it be a proper Spring Boot application.
We additionally annotate the main class with SBDG's `@EnableClusterAware` to automatically detect the {geode-name} We additionally annotate the main class with SBDG's `@EnableClusterAware` annotation to automatically detect
cluster that runs in the Docker Container and to push cluster configuration metadata from the application to the {geode-name} cluster that runs in the Docker container and to push cluster configuration metadata from
the cluster as required by the application. the application to the cluster as required by the application.
Specifically, the application requires that a region called `Customers`, as defined by the `@Region` mapping annotation Specifically, the application requires that a Region called "Customers", as defined by the `@Region` mapping annotation
on the `Customer` application domain model class, exists on the servers in the cluster, to persist `Customer` data. on the `Customer` application domain model class, exists on the servers in the cluster, to store `Customer` data.
We use the SDG `@EnableEntityDefinedRegions` annotation to define the matching client `PROXY` `Customers` Region. We use the SDG `@EnableEntityDefinedRegions` annotation to define the matching client `PROXY` "Customers" Region.
Optionally, we have also annotated our main class with SBDG's `@UseMemberName` annotation to give the `ClientCache` Optionally, we have also annotated our main class with SBDG's `@UseMemberName` annotation to give the `ClientCache`
a name, which we assert in the `assertClientCacheAndConfigureMappingPdxSerializer(:ClientCache)` method. a name, which we assert in the `assertClientCacheAndConfigureMappingPdxSerializer(:ClientCache)` method.
The primary work performed by this application is done in the Spring Boot `ApplicationRunner` bean definition. We The primary work performed by this application is done in the Spring Boot `ApplicationRunner` bean definition. We create
essentially create a `Customer` instance (`Jon Doe`), save it to the `Customers` region that is managed by the server a `Customer` instance (`Jon Doe`), save it to the "Customers" Region that is managed by the server in the cluster,
in the cluster, and then query for `Jon Doe` using OQL, asserting that the result is equal to what we expect. and then query for `Jon Doe` using OQL, asserting that the result is equal to what we expect.
We log the output from the application's operations to see the application in action. We log the output from the application's operations to see the application in action.
@@ -336,8 +345,8 @@ Process finished with exit code 0
---- ----
==== ====
When we review the configuration of the cluster, we see that the `/Customers` region was created When we review the configuration of the cluster, we see that the `/Customers` Region was created when the application
when the application ran: ran:
./Customers Region Configuration ./Customers Region Configuration
==== ====
@@ -363,7 +372,7 @@ Region | size | 1
---- ----
==== ====
Our `/Customers` region contains a value (`Jon Doe`), and we can verify this by running the following OQL Query Our `/Customers` Region contains a value (`Jon Doe`), and we can verify this by running the following OQL Query
with Gfsh: with Gfsh:
.Query the "/Customers" Region .Query the "/Customers" Region
@@ -389,6 +398,6 @@ Our application ran successfully.
In this chapter, we saw how to connect a Spring Boot, {geode-name} `ClientCache` application to an {geode-name} cluster In this chapter, we saw how to connect a Spring Boot, {geode-name} `ClientCache` application to an {geode-name} cluster
that runs in a Docker container. that runs in a Docker container.
Later, we provide more information on how to scale up, or rather scale out, our {geode-name} cluster that runs in Later, we provide more information on how to scale up, or rather scale out, our {geode-name} cluster that runs in Docker.
Docker. Additionally, we provide details on how you can use {geode-name}'s Docker Image with Testcontainers Additionally, we provide details on how you can use {geode-name}'s Docker image with Testcontainers when you write
when you write integration tests, which formally became part of the Spring Test for {geode-name} (STDG) project. integration tests, which formally became part of the Spring Test for {geode-name} (STDG) project.

View File

@@ -2,12 +2,13 @@
== Function Implementations & Executions == Function Implementations & Executions
:geode-name: {apache-geode-name} :geode-name: {apache-geode-name}
This chapter is about using {geode-name} in a Spring context for distributed computing use cases. This chapter is about using {geode-name} in a Spring context for distributed computing use cases.
=== Background === Background
Distributed processing, particularly in conjunction with data access and mutation operations, is a very effective Distributed computing, particularly in conjunction with data access and mutation operations, is a very effective
and efficient use of clustered computing resources. This is along the same lines as {wikipedia-docs}/MapReduce[MapReduce]. and efficient use of clustered computing resources. This is similar to {wikipedia-docs}/MapReduce[MapReduce].
A naively conceived query returning potentially hundreds of thousands (or even millions) of rows of data in a result set A naively conceived query returning potentially hundreds of thousands (or even millions) of rows of data in a result set
to the application that queried and requested the data can be very costly, especially under load. Therefore, it is to the application that queried and requested the data can be very costly, especially under load. Therefore, it is
@@ -19,19 +20,19 @@ can be performed much more quickly. This typically involves intelligently organi
(a.k.a. sharding) strategies to uniformly balance the data set across the cluster. (a.k.a. sharding) strategies to uniformly balance the data set across the cluster.
{geode-name} addresses this very important application concern in its {geode-name} addresses this very important application concern in its
{apache-geode-docs}/developing/function_exec/chapter_overview.html[function execution] framework. {apache-geode-docs}/developing/function_exec/chapter_overview.html[Function execution] framework.
Spring Data for {geode-name} {spring-data-geode-docs-html}/#function-annotations[builds] on this function execution Spring Data for {geode-name} {spring-data-geode-docs-html}/#function-annotations[builds] on this Function execution
framework by letting developers {spring-data-geode-docs-html}/#function-implementation[implement] framework by letting developers {spring-data-geode-docs-html}/#function-implementation[implement]
and {spring-data-geode-docs-html}/#function-execution[execute] {geode-name} functions with a simple POJO-based and {spring-data-geode-docs-html}/#function-execution[execute] {geode-name} functions with a simple POJO-based
annotation configuration model. annotation configuration model.
TIP: See {spring-data-geode-docs-html}/#_implementation_vs_execution[the section about implementation versus execution] for the difference between TIP: See {spring-data-geode-docs-html}/#_implementation_vs_execution[the section about implementation versus execution]
function implementation and execution. for the difference between Function implementation and execution.
Taking this a step further, Spring Boot for {geode-name} auto-configures and enables both function implementation Taking this a step further, Spring Boot for {geode-name} auto-configures and enables both Function implementation
and execution out-of-the-box. Therefore, you can immediately begin writing functions and invoking them without having and execution out-of-the-box. Therefore, you can immediately begin writing Functions and invoking them without having to
to worry about all the necessary plumbing to begin with. You can rest assured that it works as expected. worry about all the necessary plumbing to begin with. You can rest assured that it works as expected.
=== Applying Functions === Applying Functions
@@ -39,16 +40,15 @@ Earlier, when we talked about <<geode-caching-provider,caching>>, we described a
that could process eligibility when someone (represented by a `Person` object) applied for a financial loan. that could process eligibility when someone (represented by a `Person` object) applied for a financial loan.
This can be a very resource intensive and expensive operation, since it might involve collecting credit and employment This can be a very resource intensive and expensive operation, since it might involve collecting credit and employment
history, gathering information on outstanding loans, and so on. We applied caching history, gathering information on outstanding loans, and so on. We applied caching in order to not have to recompute
in order to not have to recompute or redetermine eligibility every time a loan office may want to review the decision or redetermine eligibility every time a loan office may want to review the decision with the customer.
with the customer.
But what about the process of computing eligibility in the first place? But, what about the process of computing eligibility in the first place?
Currently the application's `FinancialLoanApplicationService` class seems to be designed to fetch the data and perform Currently, the application's `FinancialLoanApplicationService` class seems to be designed to fetch the data and perform
the eligibility determination in place. However, it might be far better to distribute the processing and even the eligibility determination in place. However, it might be far better to distribute the processing and even determine
determine eligibility for a larger group of people all at once, especially when multiple, related people are involved eligibility for a larger group of people all at once, especially when multiple, related people are involved in a single
in a single decision, as is typically the case. decision, as is typically the case.
We can implement an `EligibilityDeterminationFunction` class by using SDG: We can implement an `EligibilityDeterminationFunction` class by using SDG:
@@ -68,8 +68,8 @@ class EligibilityDeterminationFunction {
==== ====
By using the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/annotation/GemfireFunction.html[`@GemfireFunction`] By using the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/annotation/GemfireFunction.html[`@GemfireFunction`]
annotation, we can implement our function as a POJO method. SDG appropriately handles registering this POJO method annotation, we can implement our Function as a POJO method. SDG appropriately handles registering this POJO method
as a proper function with {geode-name}. as a proper Function with {geode-name}.
If we now want to call this function from our Spring Boot `ClientCache` application, we can define If we now want to call this function from our Spring Boot `ClientCache` application, we can define
a function execution interface with a method name that matches the function name and that targets the execution a function execution interface with a method name that matches the function name and that targets the execution
@@ -88,8 +88,8 @@ interface EligibilityDeterminationExecution {
---- ----
==== ====
We can then inject the `EligibilityDeterminationExecution` into our `FinancialLoanApplicationService`, as we would any other We can then inject an instance of the `EligibilityDeterminationExecution` interface into our
object or Spring bean: `FinancialLoanApplicationService`, as we would any other object or Spring bean:
.Function use .Function use
==== ====
@@ -112,7 +112,8 @@ class FinancialLoanApplicationService {
---- ----
==== ====
As with caching, no additional configuration is required to enable and find your application function implementations As with caching, no additional configuration is required to enable and find your application Function implementations
and executions. You can simply build and run. Spring Boot for {geode-name} handles the rest. and executions. You can simply build and run. Spring Boot for {geode-name} handles the rest.
TIP: It is common to implement and register your application functions on the server and execute them from the client. TIP: It is common to "implement" and register your application Functions on the server and "execute" them from
the client.

View File

@@ -3,13 +3,13 @@
:geode-name: Apache Geode :geode-name: Apache Geode
As of Spring Boot for {geode-name} (SBDG) 1.3, you can declare {geode-name} properties from As of Spring Boot for {geode-name} (SBDG) 1.3, you can declare {geode-name} properties from `gemfire.properties`
`gemfire.properties` in a Spring Boot `application.properties` file. in Spring Boot `application.properties`.
TIP: See the {apache-geode-docs}/reference/topics/gemfire_properties.html[User Guide] TIP: See the {apache-geode-docs}/reference/topics/gemfire_properties.html[User Guide] for a complete list
for a complete list of valid {geode-name} properties. of valid {geode-name} properties.
Note that you can declare only valid Geode Properties in `gemfire.properties` or, alternatively, Note that you can declare only valid Geode properties in `gemfire.properties` or, alternatively,
`gfsecurity.properties`. `gfsecurity.properties`.
The following example shows how to declare properties in `gemfire.properties`: The following example shows how to declare properties in `gemfire.properties`:
@@ -28,10 +28,9 @@ durable-client-id=123
---- ----
==== ====
All of the properties declared in the preceding example correspond to valid Geode Properties. All of the properties declared in the preceding example correspond to valid Geode properties. It is illegal to declare
It is illegal to declare properties in a `gemfire.properties` file that are not valid Geode Properties, even if those properties in `gemfire.properties` that are not valid Geode properties, even if those properties are prefixed with a
properties are prefixed with a different qualifier (such as `spring.*`). {geode-name} different qualifier (such as `spring.*`). {geode-name} throws an `IllegalArgumentException` for invalid properties.
throws an `IllegalArgumentException` for invalid properties.
Consider the following `gemfire.properties` file with an `invalid-property`: Consider the following `gemfire.properties` file with an `invalid-property`:
@@ -48,7 +47,7 @@ invalid-property=TEST
{geode-name} throws an `IllegalArgumentException`: {geode-name} throws an `IllegalArgumentException`:
.{geode-name} Exception for Invalid Property (Full Text Omitted) .`IllegalArgumentException` thrown by {geode-name} for Invalid Property (Full Text Omitted)
==== ====
[source,txt] [source,txt]
---- ----
@@ -77,22 +76,22 @@ It is inconvenient to have to separate {geode-name} properties from other applic
only {geode-name} properties in a `gemfire.properties` file and application properties in a separate properties file, only {geode-name} properties in a `gemfire.properties` file and application properties in a separate properties file,
such as Spring Boot `application.properties`. such as Spring Boot `application.properties`.
Additionally, because of {geode-name}'s constraint on properties, you can not use the full power of Additionally, because of {geode-name}'s constraint on properties, you cannot use the full power of Spring Boot when you
Spring Boot when you compose `application.properties`. compose `application.properties`.
You can include certain properties based on a Spring profile while excluding other properties. You can include certain properties based on a Spring profile while excluding other properties. This is essential when
This is essential when properties are environment- or context-specific. properties are environment- or context-specific.
Spring Data for {geode-name} (SDG) already provide a wide range of properties mapping to Spring Data for {geode-name} already provides a wide range of properties mapping to {geode-name} properties.
{geode-name} properties.
For example, the SDG `spring.data.gemfire.locators` property maps to the `gemfire.locators` property For example, the SDG `spring.data.gemfire.locators` property maps to the `gemfire.locators` property
(`locators` in `gemfire.properties`) from {geode-name}. Likewise, there are a full set of SDG properties that map to (`locators` in `gemfire.properties`) from {geode-name}. Likewise, there are a full set of SDG properties that map to
the corresponding {geode-name} properties in the <<geode-configuration-metadata-springdata,Appendix>>. the corresponding {geode-name} properties in the <<geode-configuration-metadata-springdata,Appendix>>.
You can express the Geode properties shown earlier as SDG Properties in Spring Boot `application.properties`, as follows: You can express the Geode properties shown earlier as SDG properties in Spring Boot `application.properties`,
as follows:
.Configurring Geode Properties using SDG Properties .Configuring Geode Properties using SDG Properties
==== ====
[source,properties] [source,properties]
---- ----
@@ -100,19 +99,19 @@ You can express the Geode properties shown earlier as SDG Properties in Spring B
spring.data.gemfire.name=ExampleCacheName spring.data.gemfire.name=ExampleCacheName
spring.data.gemfire.cache.log-level=TRACE spring.data.gemfire.cache.log-level=TRACE
spring.data.gemfire.stats.enable-time-statistics=true
spring.data.gemfire.cache.client.durable-client-id=123 spring.data.gemfire.cache.client.durable-client-id=123
spring.data.gemfire.stats.enable-time-statistics=true
# ... # ...
---- ----
==== ====
However, some {geode-name} properties have no equivalent SDG property, such as `gemfire.groups` However, some {geode-name} properties have no equivalent SDG property, such as `gemfire.groups` (`groups` in
(`groups` in `gemfire.properties`). This is partly due to the fact that many {geode-name} properties are `gemfire.properties`). This is partly due to the fact that many {geode-name} properties are applicable only when
applicable only when configured on the server (such as `groups` or `enforce-unique-host`). configured on the server (such as `groups` or `enforce-unique-host`).
TIP: See the `@EnableGemFireProperties` annotation TIP: See the `@EnableGemFireProperties` annotation
({spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableGemFireProperties.html[attributes]) ({spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableGemFireProperties.html[attributes])
from SDG for a complete list of {geode-name} properties that have no corresponding SDG property. from SDG for a complete list of {geode-name} properties with no corresponding SDG property.
Furthermore, many of the SDG properties also correspond to API calls. Furthermore, many of the SDG properties also correspond to API calls.
@@ -123,8 +122,8 @@ Still, it would be convenient to be able to declare application and {geode-name}
properties file, such as Spring Boot `application.properties`. After all, it is not uncommon to declare JDBC Connection properties file, such as Spring Boot `application.properties`. After all, it is not uncommon to declare JDBC Connection
properties in a Spring Boot `application.properties` file. properties in a Spring Boot `application.properties` file.
Therefore, as of SBDG 1.3, you can now declare {geode-name} properties in Spring Boot `application.properties` Therefore, as of SBDG 1.3, you can now declare {geode-name} properties in Spring Boot `application.properties` directly,
directly, as follows: as follows:
.Geode Properties declared in Spring Boot `application.properties` .Geode Properties declared in Spring Boot `application.properties`
==== ====
@@ -142,24 +141,24 @@ gemfire.enable-time-statistics=true
This is convenient and ideal for several reasons: This is convenient and ideal for several reasons:
* If you already have a large number of {geode-name} properties declared as `gemfire.` properties (either in * If you already have a large number of {geode-name} properties declared as `gemfire.` properties (either in
`gemfire.properties` or `gfsecurity.properties`) or declared on the Java command-line as JVM System Properties `gemfire.properties` or `gfsecurity.properties`) or declared on the Java command-line as JVM System properties
(such as `-Dgemfire.name=ExampleCacheName`), you can reuse these property declarations. (such as `-Dgemfire.name=ExampleCacheName`), you can reuse these property declarations.
* If you are unfamiliar with SDG's corresponding properties, you can declare Geode Properties instead. * If you are unfamiliar with SDG's corresponding properties, you can declare Geode properties instead.
* You can take advantage of Spring features, such as Spring profiles. * You can take advantage of Spring features, such as Spring profiles.
* You can also use property placeholders with Geode Properties * You can also use property placeholders with Geode properties (such as
(such as `gemfire.log-level=${external.log-level.property}`). `gemfire.log-level=${external.log-level.property}`).
TIP: We encourage you to use the SDG properties. TIP: We encourage you to use the SDG properties, which cover more than {geode-name} properties.
However, SBDG requires that the Geode Property must have the `gemfire.` prefix in a However, SBDG requires that the Geode property must have the `gemfire.` prefix in Spring Boot `application.properties`.
Spring Boot `application.properties` file. This indicates that the property belongs to {geode-name}. Without the This indicates that the property belongs to {geode-name}. Without the `gemfire.` prefix, the property is not
`gemfire.` prefix, the property is not appropriately applied to the {geode-name} cache instance. appropriately applied to the {geode-name} cache instance.
It would be ambiguous if your Spring Boot applications integrated with several technologies, including {geode-name}, It would be ambiguous if your Spring Boot applications integrated with several technologies, including {geode-name},
and they too had matching properties, such as `bind-address` or `log-file`. and they too had matching properties, such as `bind-address` or `log-file`.
SBDG makes a best attempt to log warnings when a Geode property is invalid or is not set. For example, the following SBDG makes a best attempt to log warnings when a Geode property is invalid or is not set. For example, the following
Geode Property would result in a log warning: Geode property would result in logging a warning:
.Invalid {geode-name} Property .Invalid {geode-name} Property
==== ====
@@ -174,6 +173,7 @@ gemfire.non-existing-property=TEST
The resulting warning in the log would read: The resulting warning in the log would read:
.Invalid Geode Property Warning Message
==== ====
[source,text] [source,text]
---- ----
@@ -183,6 +183,7 @@ The resulting warning in the log would read:
If a Geode Property is not properly set, the following warning is logged: If a Geode Property is not properly set, the following warning is logged:
.Invalide Geode Property Value Warning Message
==== ====
[source,text] [source,text]
---- ----
@@ -190,8 +191,8 @@ Apache Geode Property [gemfire.security-manager] was not set
---- ----
==== ====
With regards to the third point mentioned earlier, you can now compose and declare Geode Properties based on a context (such as your application With regards to the third point mentioned earlier, you can now compose and declare Geode properties based on a context
environment) with Spring profiles. (such as your application environment) using Spring profiles.
For example, you might start with a base set of properties in Spring Boot `application.properties`: For example, you might start with a base set of properties in Spring Boot `application.properties`:
@@ -223,7 +224,6 @@ gemfire.groups=QA
---- ----
==== ====
.Production Properties .Production Properties
==== ====
[source,properties] [source,properties]
@@ -240,16 +240,17 @@ gemfire.groups=PROD
---- ----
==== ====
You can then apply the appropriate set of properties by configuring the Spring Profile with You can then apply the appropriate set of properties by configuring the Spring profile with
`-Dspring.profiles.active=prod`. You can also enable more than one profile at a time with `-Dspring.profiles.active=prod`. You can also enable more than one profile at a time with
`-Dspring.profiles.active=profile1,profile2,...,profileN` `-Dspring.profiles.active=profile1,profile2,...,profileN`
If both `spring.data.gemfire.*` properties and the matching {geode-name} properties are declared in Spring Boot If both `spring.data.gemfire.*` properties and the matching {geode-name} properties are declared in Spring Boot
`application.properties`, the SDG properties take precedence. `application.properties`, the SDG properties take precedence.
If a property is specified more than once, as would potentially be the case when composing multiple `application.properties` If a property is specified more than once, as would potentially be the case when composing multiple Spring Boot
files and you enable more than one Spring Profile at time, the last property declaration wins. In the example shown `application.properties` files and you enable more than one Spring profile at time, the last property declaration wins.
earlier, the value for `gemfire.groups` would be `PROD` when `-Dspring.profiles.active=qa,prod` is configured. In the example shown earlier, the value for `gemfire.groups` would be `PROD` when `-Dspring.profiles.active=qa,prod`
is configured.
Consider the following Spring Boot `application.properties`: Consider the following Spring Boot `application.properties`:
@@ -264,12 +265,12 @@ spring.data.gemfire.cache.client.durable-client-id=987
---- ----
==== ====
The `durable-client-id` is `987`. It does not matter which order the SDG or {geode-name} properties are The `durable-client-id` is `987`. It does not matter which order the SDG or {geode-name} properties are declared in
declared in `application.properties`. The matching SDG property overrides the {geode-name} property when duplicates Spring Boot `application.properties`. The matching SDG property overrides the {geode-name} property when duplicates
are found. are found.
Finally, you cannot refer to Geode Properties declared in Spring Boot `application.properties` with the Finally, you cannot refer to Geode properties declared in Spring Boot `application.properties` with the SBDG
SBDG `GemFireProperties` class (see the {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/GemFireProperties.html[Javadoc]). `GemFireProperties` class (see the {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/GemFireProperties.html[Javadoc]).
Consider the following example: Consider the following example:
@@ -305,11 +306,11 @@ class GemFirePropertiesTestSuite {
---- ----
==== ====
TIP: You can declare `application.properties` in the `@SpringBootTest` annotation. For example, you could have declared `gemfire.name` TIP: You can declare `application.properties` in the `@SpringBootTest` annotation. For example, you could have declared
in the annotation by setting `@SpringBootTest(properties = { "gemfire.name=TestCacheName" })` `gemfire.name` in the annotation by setting `@SpringBootTest(properties = { "gemfire.name=TestCacheName" })`
for testing purposes instead of declaring the property in a separate `application.properties` file. for testing purposes instead of declaring the property in a separate Spring Boot `application.properties` file.
Only `spring.data.gemfire.*` prefixed properties are mapped to the SBDG `GemFireProperties` class hierarchy. Only `spring.data.gemfire.*` prefixed properties are mapped to the SBDG `GemFireProperties` class hierarchy.
TIP: Prefer SDG Properties over Geode Properties. See the SDG properties reference TIP: Prefer SDG properties over Geode properties. See the SDG properties reference
in the <<geode-configuration-metadata-springdata,Appendix>>. in the <<geode-configuration-metadata-springdata,Appendix>>.

View File

@@ -8,9 +8,8 @@ When using the Spring programming model and abstractions, it should not be neces
or the Spring Data Repository abstraction for DAO development. There are many more examples. or the Spring Data Repository abstraction for DAO development. There are many more examples.
For certain use cases, users may require low level access to fine-grained functionally. Spring Boot for {geode-name}'s For certain use cases, users may require low level access to fine-grained functionally. Spring Boot for {geode-name}'s
`org.springframework.geode:apache-geode-extensions` module and library builds on {geode-name}'s APIs `org.springframework.geode:apache-geode-extensions` module and library builds on {geode-name}'s APIs by including
by including several extensions with enhanced functionality to offer an experience familiar to Spring users several extensions with enhanced functionality to offer an experience familiar to Spring users inside a Spring context.
inside a Spring context.
TIP: Spring Data for {geode-name} (SDG) also {spring-data-geode-docs-html}/#apis[includes] additional extensions to TIP: Spring Data for {geode-name} (SDG) also {spring-data-geode-docs-html}/#apis[includes] additional extensions to
{geode-name}'s APIs. {geode-name}'s APIs.
@@ -23,13 +22,14 @@ For example, you might want to create a temporary `Region` on the fly to aggrega
Typically, you already know the type of cache your application is using, since you must declare your application to be Typically, you already know the type of cache your application is using, since you must declare your application to be
either a client (`ClientCache`) in the {apache-geode-docs}/topologies_and_comm/cs_configuration/chapter_overview.html[client/server topology], either a client (`ClientCache`) in the {apache-geode-docs}/topologies_and_comm/cs_configuration/chapter_overview.html[client/server topology],
or a {apache-geode-docs}/topologies_and_comm/p2p_configuration/chapter_overview.html[peer member or node] in the cluster or a {apache-geode-docs}/topologies_and_comm/p2p_configuration/chapter_overview.html[peer member or node] (`Cache`) in
(`Cache`) on startup. This is expressed in configuration when creating the cache instance required to interact with the cluster on startup. This is expressed in configuration when creating the cache instance required to interact with
the {geode-name} data management system. In most cases, your application can be a client. SBDG makes this decision the {geode-name} data management system. In most cases, your application will be a client. SBDG makes this decision easy,
easy, since it auto-configures a `ClientCache` instance, <<geode-clientcache-applications,by default>>. since it auto-configures a `ClientCache` instance, <<geode-clientcache-applications,by default>>.
In a Spring context, the cache instance created by the framework is a managed bean in the Spring container. In a Spring context, the cache instance created by the framework is a managed bean in the Spring container.
You can inject a reference to the singleton cache bean into any other managed application component: You can inject a reference to the https://en.wikipedia.org/wiki/Singleton_pattern[_Singleton_] cache bean
into any other managed application component:
.Autowired Cache Reference using Dependency Injection (DI) .Autowired Cache Reference using Dependency Injection (DI)
==== ====
@@ -71,13 +71,13 @@ abstract class SimpleCacheResolver {
---- ----
==== ====
`SimpleCacheResolver` adheres to https://en.wikipedia.org/wiki/SOLID[SOLID OO Principles]. This class is abstract and `SimpleCacheResolver` adheres to https://en.wikipedia.org/wiki/SOLID[SOLID OO Principles]. This class is abstract
extensible so that you can change the algorithm used to resolve client or peer cache instances as well as mock its methods and extensible so that you can change the algorithm used to resolve client or peer cache instances as well as mock
in unit tests. its methods in unit tests.
Additionally, each method is precise. For example, `resolveClientCache()` resolves a reference to a cache only if Additionally, each method is precise. For example, `resolveClientCache()` resolves a reference to a cache only if
the cache instance is a "`client.`" If a cache exists but is a "`peer`" instance, `resolveClientCache()` returns the cache instance is a "`client.`" If a cache exists but is a "`peer`" cache instance, `resolveClientCache()`
`Optional.EMPTY`. The behavior of `resolvePeerCache()` is similar. returns `Optional.EMPTY`. The behavior of `resolvePeerCache()` is similar.
`require()` returns a non-`Optional` reference to a cache instance and throws an `IllegalStateException` if a cache `require()` returns a non-`Optional` reference to a cache instance and throws an `IllegalStateException` if a cache
is not present. is not present.
@@ -89,17 +89,17 @@ Under the hood, `SimpleCacheResolver` delegates some of its functions to the
{spring-boot-data-geode-javadoc}/org/springframework/geode/util/CacheUtils.html[`CacheUtils`] {spring-boot-data-geode-javadoc}/org/springframework/geode/util/CacheUtils.html[`CacheUtils`]
abstract utility class, which provides additional, convenient capabilities when you use a cache. abstract utility class, which provides additional, convenient capabilities when you use a cache.
While there are utility methods to determine whether a cache instance (that is, a `GemFireCache`) or region is a client While there are utility methods to determine whether a cache instance (that is, a `GemFireCache`) or Region is a client
or a peer, one of the more useful functions is to extract all the values from a region. or a peer, one of the more useful functions is to extract all the values from a Region.
To extract all the values stored in a region, call `CacheUtils.collectValues(:Region<?, T>)`. This method returns a To extract all the values stored in a Region, call `CacheUtils.collectValues(:Region<?, T>)`. This method returns a
`Collection<T>` that contains all the values stored in the given region. The method is smart and knows how to handle `Collection<T>` that contains all the values stored in the given `Region`. The method is smart and knows how to handle
the `Region` appropriately regardless of whether the `Region` is a client or apeer. This distinction is the `Region` appropriately regardless of whether the `Region` is a client or a peer. This distinction is important,
important, since client `PROXY` regions store no values. since client `PROXY` Regions store no values.
WARNING: Caution is advised when you get all values from a region. While getting filtered reference values from a WARNING: Caution is advised when you get all values from a Region. While getting filtered reference values from a
non-transactional, reference data only [`REPLICATE`] region is quite useful, getting all values from a transactional, non-transactional, reference data only [`REPLICATE`] Region is quite useful, getting all values from a transactional,
[`PARTITION`] region can prove quite detrimental, especially in production. Getting all values from a region can be [`PARTITION`] Region can prove quite detrimental, especially in production. Getting all values from a Region can be
useful during testing. useful during testing.
[[geode-api-extensions-membership]] [[geode-api-extensions-membership]]
@@ -110,23 +110,23 @@ on the server side when your Spring Boot application serves as a peer member of
When a peer member is disconnected from the distributed system, perhaps due to a network failure, the member is forcibly When a peer member is disconnected from the distributed system, perhaps due to a network failure, the member is forcibly
removed from the cluster. This node immediately enters a reconnecting state, trying to establish a connection back to removed from the cluster. This node immediately enters a reconnecting state, trying to establish a connection back to
the cluster. Once reconnected, the peer member must rebuild all cache objects (`Cache`, `Region` instances, `Index` instance, the cluster. Once reconnected, the peer member must rebuild all cache objects (`Cache`, `Region` instances, `Index`
`DiskStore` instances, and so on). All previous cache objects are now invalid, and their references are stale. instances, `DiskStore` instances, and so on). All previous cache objects are now invalid, and their references are stale.
in a Spring context, this is particularly problematic since most {geode-name} objects are singleton In a Spring context, this is particularly problematic since most {geode-name} objects are _Singleton_ beans declared in
beans declared in and managed by the Spring container. Those beans may be injected and used in other framework and and managed by the Spring container. Those beans may be injected and used in other framework and application components.
application components. For instance, `Region` instances are injected into SDG's `GemfireTemplate`, Spring Data repositories For instance, `Region` instances are injected into SDG's `GemfireTemplate`, Spring Data Repositories and possibly
and possibly application-specific data access objects (https://en.wikipedia.org/wiki/Data_access_object[DAOs]). application-specific data access objects (https://en.wikipedia.org/wiki/Data_access_object[DAOs]).
If references to those cache objects become stale on a forced disconnect event, there is no way to auto-wire fresh If references to those cache objects become stale on a forced disconnect event, there is no way to auto-wire fresh
object references into the dependent application or framework components when the peer member is reconnected, unless the object references into the dependent application or framework components when the peer member is reconnected, unless the
Spring `ApplicationContext` is "`refreshed`". In fact, there is no way to even know that this event has occurred, since the Spring `ApplicationContext` is "`refreshed`". In fact, there is no way to even know that this event has occurred, since
{geode-name} `MembershipListener` API and corresponding events are "`internal`". the {geode-name} `MembershipListener` API and corresponding events are "`internal`".
NOTE: The Spring team explored the idea of creating proxies for all types of cache objects (`Cache`, `Region`, NOTE: The Spring team explored the idea of creating proxies for all types of cache objects (`Cache`, `Region`, `Index`,
`Index`, `DiskStore`, `AsyncEventQueue`, `GatewayReceiver`, `GatewaySender`, and others) used by Spring. The proxies `DiskStore`, `AsyncEventQueue`, `GatewayReceiver`, `GatewaySender`, and others) used by Spring. The proxies would know
would know how to obtain a "`fresh`" reference on a reconnect event. However, this turns out to be more problematic than how to obtain a fresh reference on a reconnect event. However, this turns out to be more problematic than it is worth.
it is worth. It is easier to "`refresh`" the Spring `ApplicationContext`, although doing so is no less expensive. Neither way is It is easier to "`refresh`" the Spring `ApplicationContext`, although doing so is no less expensive. Neither way is
ideal. See https://jira.spring.io/browse/SGF-921[SGF-921] and https://jira.spring.io/browse/SGF-227[SGF-227] ideal. See https://jira.spring.io/browse/SGF-921[SGF-921] and https://jira.spring.io/browse/SGF-227[SGF-227]
for further details. for further details.
@@ -136,9 +136,9 @@ In the case where membership events are useful to the Spring Boot application, S
* {spring-boot-data-geode-javadoc}/org/springframework/geode/distributed/event/MembershipListenerAdapter.html[`MembershipListenerAdapter`] * {spring-boot-data-geode-javadoc}/org/springframework/geode/distributed/event/MembershipListenerAdapter.html[`MembershipListenerAdapter`]
* {spring-boot-data-geode-javadoc}/org/springframework/geode/distributed/event/MembershipEvent.html[`MembershipEvent`] * {spring-boot-data-geode-javadoc}/org/springframework/geode/distributed/event/MembershipEvent.html[`MembershipEvent`]
The abstract `MembershipListenerAdapter` class implements {geode-name}'s `org.apache.geode.distributed.internal.MembershipListener` interface The abstract `MembershipListenerAdapter` class implements {geode-name}'s `org.apache.geode.distributed.internal.MembershipListener`
to simplify the event handler method signatures by using an appropriate `MembershipEvent` type interface to simplify the event handler method signatures by using an appropriate `MembershipEvent` type to encapsulate
to encapsulate the actors in the event. the actors in the event.
The abstract `MembershipEvent` class is further subclassed to represent specific membership event types that occur The abstract `MembershipEvent` class is further subclassed to represent specific membership event types that occur
within the {geode-name} system: within the {geode-name} system:
@@ -161,7 +161,7 @@ The type hierarchy is useful in `instanceof` expressions, while the `Enum` is us
You can see one particular implementation of the `MembershipListenerAdapter` with the You can see one particular implementation of the `MembershipListenerAdapter` with the
{spring-boot-data-geode-javadoc}/org/springframework/geode/distributed/event/ApplicationContextMembershipListener.html[`ApplicationContextMembershipListener`] class, {spring-boot-data-geode-javadoc}/org/springframework/geode/distributed/event/ApplicationContextMembershipListener.html[`ApplicationContextMembershipListener`] class,
which does exactly as we described earlier, handling forced-disconnect/auto-reconnect membership events inside a which does exactly as we described earlier, handling forced-disconnect/auto-reconnect membership events inside a
Spring context in order to refresh the Spring `ApplicationContext`. Spring container in order to refresh the Spring `ApplicationContext`.
[[geode-api-extensions-pdx]] [[geode-api-extensions-pdx]]
=== PDX === PDX
@@ -169,17 +169,17 @@ Spring context in order to refresh the Spring `ApplicationContext`.
{geode-name}'s PDX serialization framework is yet another API that falls short of a complete stack. {geode-name}'s PDX serialization framework is yet another API that falls short of a complete stack.
For instance, there is no easy or direct way to serialize an object as PDX bytes. It is also not possible to modify an For instance, there is no easy or direct way to serialize an object as PDX bytes. It is also not possible to modify an
existing `PdxInstance` by adding or removing fields, since doing so would require a new PDX type. In this case, you must create a existing `PdxInstance` by adding or removing fields, since doing so would require a new PDX type. In this case, you must
new `PdxInstance` and copy from the existing `PdxInstance`. Unfortunately, the {geode-name} API offers no assistance. create a new `PdxInstance` and copy from an existing `PdxInstance`. Unfortunately, the {geode-name} API offers no help
It is also not possible to use PDX in a client, local-only mode without a server, since the PDX type registry is only in this regard. It is also not possible to use PDX in a client, local-only mode without a server, since the PDX type
available and managed on servers in a cluster. All of this leaves much to be desired. registry is only available and managed on servers in a cluster.
[[geode-api-extensions-pdx-builder]] [[geode-api-extensions-pdx-builder]]
==== `PdxInstanceBuilder` ==== `PdxInstanceBuilder`
In such cases, SBDG conveniently provides the In such cases, SBDG conveniently provides the
{spring-boot-data-geode-javadoc}/org/springframework/geode/pdx/PdxInstanceBuilder.html[`PdxInstanceBuilder`] class, {spring-boot-data-geode-javadoc}/org/springframework/geode/pdx/PdxInstanceBuilder.html[`PdxInstanceBuilder`] class,
appropriately named after the https://en.wikipedia.org/wiki/Builder_pattern[builder software design pattern_]. appropriately named after the https://en.wikipedia.org/wiki/Builder_pattern[Builder software design pattern].
The `PdxInstanceBuilder` also offers a fluent API for constructing `PdxInstances`: The `PdxInstanceBuilder` also offers a fluent API for constructing `PdxInstances`:
.`PdxInstanceBuilder` API .`PdxInstanceBuilder` API
@@ -250,8 +250,10 @@ JSON back into a POJO. Specifically, the wrapper gives you more control over the
The `ObjectMapper` constructed by {geode-name}'s own `PdxInstance` implementation (`PdxInstanceImpl`) is not The `ObjectMapper` constructed by {geode-name}'s own `PdxInstance` implementation (`PdxInstanceImpl`) is not
configurable, nor was it configured correctly. Unfortunately, since `PdxInstance` is not extensible, the `getObject()` configurable, nor was it configured correctly. Unfortunately, since `PdxInstance` is not extensible, the `getObject()`
method fails when converting the JSON generated from PDX back into a POJO for any practical application domain method fails when converting the JSON generated from PDX back into a POJO for any practical application domain model
model type. type.
The following example wraps an existing `PdxInstance`:
The following example wraps an existing `PdxInstance`: The following example wraps an existing `PdxInstance`:
@@ -267,28 +269,28 @@ For all operations on `PdxInstance` except `getObject()`, the wrapper delegates
implementation called by the user. implementation called by the user.
In addition to the decorated `getObject()` method, the `PdxInstanceWrapper` provides a thorough implementation of the In addition to the decorated `getObject()` method, the `PdxInstanceWrapper` provides a thorough implementation of the
`toString()` method. The state of the `PdxInstance` is output in a JSON-like String. `toString()` method. The state of the `PdxInstance` is output in a JSON-like `String`.
Finally, the `PdxInstanceWrapper` class adds a `getIdentifier()` method. Rather than put the burden on the user to have Finally, the `PdxInstanceWrapper` class adds a `getIdentifier()` method. Rather than put the burden on the user to have
to iterate the field names of the `PdxInstance` to determine whether a field is the identity field and then call to iterate the field names of the `PdxInstance` to determine whether a field is the identity field and then call
`getField(..)` with the field name to get the ID (value) -- assuming an identity field was marked in the first place -- `getField(name)` with the field name to get the ID (value) -- assuming an identity field was marked in the first place
the `PdxInstanceWrapper` class provides the `getIdentifier()` method to return the ID of the `PdxInstance` directly. -- the `PdxInstanceWrapper` class provides the `getIdentifier()` method to return the ID of the `PdxInstance` directly.
The `getIdentifier()` method is smart in that it first iterates the fields of the `PdxInstance`, asking each field if it is The `getIdentifier()` method is smart in that it first iterates the fields of the `PdxInstance`, asking each field if it
the identity field. If no field was marked as the `identity` field, the algorithm searches for a field named `id`. is the identity field. If no field was marked as the identity field, the algorithm searches for a field named `id`. If
If no field with the name `id` exists, the algorithm searches for a metadata field called `@identifier`, which no field with the name `id` exists, the algorithm searches for a metadata field called `@identifier`, which refers to
refers to the field that is the identity field of the `PdxInstance`. the field that is the identity field of the `PdxInstance`.
The `@identifier` metadata field is useful in cases where the `PdxInstance` originated from JSON and the application The `@identifier` metadata field is useful in cases where the `PdxInstance` originated from JSON and the application
domain object uses a natural identifier, rather than a surrogate ID, such as `Book.isbn`. domain object uses a natural identifier, rather than a surrogate ID, such as `Book.isbn`.
NOTE: {geode-name}'s `JSONFormatter` is not capable of marking the identity field of a `PdxInstance` originating NOTE: {geode-name}'s `JSONFormatter` class is not capable of marking the identity field of a `PdxInstance` originating
from JSON. from JSON.
WARNING: It is not currently possible to implement the `PdxInstance` interface and store instances of this type as a WARNING: It is not currently possible to implement the `PdxInstance` interface and store instances of this type as a
value in a region. {geode-name} naively assumes that all `PdxInstance` objects are an implementation created by value in a Region. {geode-name} assumes all `PdxInstance` objects are an implementation created by {geode-name} itself
{geode-name} itself (that is, `PdxInstanceImpl`), which has a tight coupling to the PDX type registry. An `Exception` is (that is, `PdxInstanceImpl`), which has a tight coupling to the PDX type registry. An `Exception` is thrown if you try
thrown if you try to store instances of your own `PdxInstance` implementation. to store instances of your own `PdxInstance` implementation.
[[geode-api-extensions-pdx-adapter]] [[geode-api-extensions-pdx-adapter]]
==== `ObjectPdxInstanceAdapter` ==== `ObjectPdxInstanceAdapter`
@@ -296,13 +298,13 @@ thrown if you try to store instances of your own `PdxInstance` implementation.
In rare cases, you may need to treat an `Object` as a `PdxInstance`, depending on the context without incurring In rare cases, you may need to treat an `Object` as a `PdxInstance`, depending on the context without incurring
the overhead of serializing an `Object` to PDX. For such cases, SBDG offers the `ObjectPdxInstanceAdapter` class. the overhead of serializing an `Object` to PDX. For such cases, SBDG offers the `ObjectPdxInstanceAdapter` class.
This might be true when calling a method with a parameter that expects an argument or when returning an instance of type This might be true when calling a method with a parameter expecting an argument of, or returning an instance of,
`PdxInstance`, particularly when {geode-name}'s `read-serialized` PDX configuration property is set to `true` and only type `PdxInstance`, particularly when {geode-name}'s `read-serialized` PDX configuration property is set to `true`
an object is available in the current context. and only an object is available in the current context.
Under the hood, SBDG's `ObjectPdxInstanceAdapter` class uses Spring's Under the hood, SBDG's `ObjectPdxInstanceAdapter` class uses Spring's
{spring-framework-javadoc}/org/springframework/beans/BeanWrapper.html[`BeanWrapper`] class along with Java's {spring-framework-javadoc}/org/springframework/beans/BeanWrapper.html[`BeanWrapper`] class along with Java's
introspection and reflection functionality to adapt the given `Object`, in order to access it with the full introspection and reflection functionality to adapt the given `Object` and access it with the full
{apache-geode-javadoc}/org/apache/geode/pdx/PdxInstance.html[`PdxInstance`] API. This includes the use of the {apache-geode-javadoc}/org/apache/geode/pdx/PdxInstance.html[`PdxInstance`] API. This includes the use of the
{apache-geode-javadoc}/org/apache/geode/pdx/WritablePdxInstance.html[`WritablePdxInstance`] API, obtained from {apache-geode-javadoc}/org/apache/geode/pdx/WritablePdxInstance.html[`WritablePdxInstance`] API, obtained from
{apache-geode-javadoc}/org/apache/geode/pdx/PdxInstance.html#createWriter--[`PdxInstance.createWriter()`], to modify {apache-geode-javadoc}/org/apache/geode/pdx/PdxInstance.html#createWriter--[`PdxInstance.createWriter()`], to modify
@@ -310,8 +312,8 @@ the underlying `Object` as well.
Like the `PdxInstanceWrapper` class, `ObjectPdxInstanceAdapter` contains special logic to resolve the identity field Like the `PdxInstanceWrapper` class, `ObjectPdxInstanceAdapter` contains special logic to resolve the identity field
and ID of the `PdxInstance`, including consideration for Spring Data's and ID of the `PdxInstance`, including consideration for Spring Data's
{spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`@Id`] mapping annotation, which can be {spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`@Id`] mapping annotation,
introspected in this case, given that the underlying `Object` backing the `PdxInstance` is a POJO. which can be introspected in this case, given that the underlying `Object` backing the `PdxInstance` is a POJO.
The `ObjectPdxInstanceAdapter.getObject()` method returns the wrapped `Object` used to construct The `ObjectPdxInstanceAdapter.getObject()` method returns the wrapped `Object` used to construct
the `ObjectPdxInstanceAdapter` and is, therefore, automatically deserializable, as determined by the the `ObjectPdxInstanceAdapter` and is, therefore, automatically deserializable, as determined by the
@@ -333,7 +335,8 @@ class OfflineObjectToPdxInstanceConverter {
---- ----
==== ====
Once the adapter is created, you can use it to access data on the underlying `Object`. Once the https://en.wikipedia.org/wiki/Adapter_pattern[Adapter] is created, you can use it to access data
on the underlying `Object`.
Consider the following example of a `Customer` class: Consider the following example of a `Customer` class:
@@ -385,11 +388,12 @@ class ObjectPdxInstanceAdapterTest {
[[geode-api-extensions-security]] [[geode-api-extensions-security]]
=== Security === Security
For testing purposes, SBDG provides a test implementation of {geode-name}'s {apache-geode-javadoc}/org/apache/geode/security/SecurityManager.html[`SecurityManager`] For testing purposes, SBDG provides a test implementation of
interface, which expects the password to match the username (case-sensitive) when authenticating. {geode-name}'s {apache-geode-javadoc}/org/apache/geode/security/SecurityManager.html[`SecurityManager`] interface,
which expects the password to match the username (case-sensitive) when authenticating.
By default, all operations are authorized. By default, all operations are authorized.
To match the expectations of SBDG's `TestSecurityManager`, SBDG additionally provides a test implementation of To match the expectations of SBDG's `TestSecurityManager`, SBDG additionally provides a test implementation of
{geode-name}'s {apache-geode-javadoc}/org/apache/geode/security/AuthInitialize.html[`AuthInitialize`] interface, which {geode-name}'s {apache-geode-javadoc}/org/apache/geode/security/AuthInitialize.html[`AuthInitialize`] interface,
supplies matching credentials for both the username and password. which supplies matching credentials for both the username and password.

View File

@@ -2,30 +2,30 @@
== Logging == Logging
:geode-name: Apache Geode :geode-name: Apache Geode
{geode-name} `1.9.2` was modularized to separate its use of the Apache Log4j API to log output in Geode code from
the underlying implementation of logging, which uses Apache Log4j as the logging provider by default.
Prior to `1.9.2`, the Apache Log4j API (`log4j-api`) and the Apache Log4j provider (`log4j-core`) {geode-name} `1.9.2` was modularized to separate its use of the Apache Log4j API to log output in {geode-name} code
from the underlying implementation of logging, which uses Apache Log4j as the logging provider by default.
Prior to `1.9.2`, the Apache Log4j API (`log4j-api`) and the Apache Log4j service provider (`log4j-core`)
were automatically pulled in by {geode-name} core (`org.apache.geode:geode-core`), thereby making it problematic were automatically pulled in by {geode-name} core (`org.apache.geode:geode-core`), thereby making it problematic
to change logging providers when using {geode-name} in Spring Boot applications. to change logging providers when using {geode-name} in Spring Boot applications.
However, now, in order to get any log output from {geode-name} whatsoever, {geode-name} requires a logging provider on However, now, in order to get any log output from {geode-name} whatsoever, {geode-name} requires a logging provider
your Spring Boot application classpath. Consequently, this also means the old {geode-name} `Properties` declared on your Spring Boot application classpath. Consequently, this also means the old {geode-name} `Properties`
(such as `log-level`) no longer have any effect, regardless of whether the property is specified in (such as `log-level`) no longer have any effect, regardless of whether the property is specified in `gemfire.properties`,
`gemfire.properties`, in Spring Boot `application.properties`, or even as a JVM System Property (`-Dgemfire.log-level`). in Spring Boot `application.properties`, or even as a JVM System Property (`-Dgemfire.log-level`).
TIP: See {geode-name}'s {apache-geode-docs}/reference/topics/gemfire_properties.html[documentation] TIP: See {geode-name}'s {apache-geode-docs}/reference/topics/gemfire_properties.html[documentation] for a complete list
for a complete list of valid `Properties`, including the `Properties` used to configure logging. of valid `Properties`, including the `Properties` used to configure logging.
Unfortunately, this also means the Spring Data for {geode-name} (SDG) Unfortunately, this also means the Spring Data for {geode-name}
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLogging.html[`@EnableLogging`] {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableLogging.html[`@EnableLogging`]
annotation no longer has any effect on {geode-name} logging either. Consequently, it has been annotation no longer has any effect on {geode-name} logging either. Consequently, it has been
https://jira.spring.io/browse/DATAGEODE-299[deprecated]. The reason `@EnableLogging` no longer has any effect on logging https://jira.spring.io/browse/DATAGEODE-299[deprecated]. The reason `@EnableLogging` no longer has any effect on logging
is because this annotation's attributes and associated SDG properties indirectly set the corresponding {geode-name} is because this annotation's attributes and associated SDG properties indirectly set the corresponding {geode-name}
properties, which, again, are useless from {geode-name} `1.9.2` onward. properties, which, again, are useless from {geode-name} `1.9.2` onward.
By way of example, and to make this concrete, *none* of the following approaches have any effect on By way of example, and to make this concrete, *none* of the following approaches have any effect on {geode-name} logging:
{geode-name} logging:
.Command-line configuration .Command-line configuration
==== ====
@@ -50,7 +50,6 @@ log-level=INFO
[source,properties] [source,properties]
---- ----
spring.data.gemfire.cache.log-level=DEBUG spring.data.gemfire.cache.log-level=DEBUG
spring.data.gemfire.logging.level=DEBUG spring.data.gemfire.logging.level=DEBUG
---- ----
==== ====
@@ -62,7 +61,7 @@ spring.data.gemfire.logging.level=DEBUG
@SpringBootApplication @SpringBootApplication
@EnableLogging(logLevel = "DEBUG") @EnableLogging(logLevel = "DEBUG")
class MySpringBootApacheGeodeClientApplication { class MySpringBootApacheGeodeClientApplication {
// ...
} }
---- ----
==== ====
@@ -74,56 +73,56 @@ None of the preceding approaches have any effect without the *new* SBDG logging
So, how do you configure logging for {geode-name}? So, how do you configure logging for {geode-name}?
Effectively, three things are required to get {geode-name} to log output: Three things are required to get {geode-name} to log output:
. You must declare a logging provider (such as Logback) on your Spring Boot application classpath. . You must declare a logging provider (such as Logback) on your Spring Boot application classpath.
. (optional) You can declare an adapter (or bridge JAR) between Log4j and your logging provider if your declared . (optional) You can declare an adapter (a bridge JAR) between Log4j and your logging provider if your declared
logging provider is not Apache Log4j. logging provider is not Apache Log4j.
+ +
For example, if you use the SLF4J API to log output from your Spring Boot application and use Logback as your For example, if you use the SLF4J API to log output from your Spring Boot application and use Logback as your
logging provider or implementation, you must include the `org.apache.logging.log4j.log4j-to-slf4j` adapter or bridge JAR logging provider or implementation, you must include the `org.apache.logging.log4j.log4j-to-slf4j` adapter or
dependency as well. bridge JAR as well.
+ +
Internally, {geode-name} uses the Apache Log4j API to log output from Geode components. Therefore, you must bridge Log4j Internally, {geode-name} uses the Apache Log4j API to log output from Geode components. Therefore, you must bridge Log4j
to any other logging provider (such as Logback) that is not Log4j (`log4j-core`). If you use Log4j as your to any other logging provider (such as Logback) that is not Log4j (`log4j-core`). If you use Log4j as your
logging provider, you need not declare an adapter or bridge JAR on your Spring Boot application classpath. logging provider, you need not declare an adapter or bridge JAR on your Spring Boot application classpath.
. Finally, you must supply logging provider configuration to configure loggers, appenders, log levels, and other details. . Finally, you must supply logging provider configuration to configure Loggers, Appenders, log levels, and other details.
+
For example, when you use Logback, you must provide a `logback.xml` configuration file on your Spring Boot application For example, when you use Logback, you must provide a `logback.xml` configuration file on your Spring Boot application
classpath or in the filesystem. Alternatively, you can use other means to configure your logging provider and get classpath or in the filesystem. Alternatively, you can use other means to configure your logging provider and get
{geode-name} to log output. {geode-name} to log output.
NOTE: {geode-name}'s `geode-log4j` module covers the required configuration for steps 1-3 above and uses Apache Log4j NOTE: {geode-name}'s `geode-log4j` module covers the required configuration for steps 1-3 above and uses Apache Log4j
(`org.apache.logging.log4j:log4j-core`) as the logging provider. The `geode-log4j` module even provides a default (`org.apache.logging.log4j:log4j-core`) as the logging provider. The `geode-log4j` module even provides a default
`log4j2.xml` configuration file to configure loggers, appenders, and log levels for {geode-name}. `log4j2.xml` configuration file to configure Loggers, Appenders, and log levels for {geode-name}.
If you declare Spring Boot's own `org.springframework.boot:spring-boot-starter-logging` on your application classpath, If you declare Spring Boot's own `org.springframework.boot:spring-boot-starter-logging` on your application classpath,
it covers steps 1 and 2 above. it covers steps 1 and 2 above.
The `spring-boot-starter-logging` dependency declares Logback as the logging provider and automatically adapts The `spring-boot-starter-logging` dependency declares Logback as the logging provider and automatically adapts (bridges)
(or bridges) `java.util.logging` (JUL) and Apache Log4j to SLF4J. However, you still need to supply logging provider `java.util.logging` (JUL) and Apache Log4j to SLF4J. However, you still need to supply logging provider configuration
configuration (such as a `logback.xml` file for Logback) to configure logging not only for your Spring Boot (such as a `logback.xml` file for Logback) to configure logging not only for your Spring Boot application but for
application but for {geode-name} as well. {geode-name} as well.
SBDG has simplified the setup of {geode-name} logging. You need only declare the SBDG has simplified the setup of {geode-name} logging. You need only declare the
`org.springframework.geode:spring-geode-starter-logging` dependency on your Spring Boot application classpath. `org.springframework.geode:spring-geode-starter-logging` dependency on your Spring Boot application classpath.
Unlike {geode-name}'s default Log4j XML configuration file (`log4j2.xml`), SBDG's provided `logback.xml` Unlike {geode-name}'s default Log4j XML configuration file (`log4j2.xml`), SBDG's provided `logback.xml` configuration
configuration file is properly parameterized, letting you adjust log levels as well as add appenders. file is properly parameterized, letting you adjust log levels as well as add Appenders.
In addition, SBDG's provided Logback configuration uses templates so that you can compose your own logging configuration In addition, SBDG's provided Logback configuration uses templates so that you can compose your own logging configuration
while still "`including`" snippets from SBDG's provided logging configuration metadata, such as loggers and appenders. while still including snippets from SBDG's provided logging configuration metadata, such as Loggers and Appenders.
[[geode-logging-configuration-log-levels]] [[geode-logging-configuration-log-levels]]
==== Configuring Log Levels ==== Configuring Log Levels
One of the most common logging tasks is to adjust the log level of one or more loggers or the root logger. However, One of the most common logging tasks is to adjust the log level of one or more Loggers or the ROOT Logger. However,
you may want only to adjust the log level for specific components of your Spring Boot application, such as for you may want to only adjust the log level for specific components of your Spring Boot application, such as for
{geode-name}, by setting the log level for only the logger that logs {geode-name} events. {geode-name}, by setting the log level for only the Logger that logs {geode-name} events.
SBDG's Logback configuration defines three Loggers to control the log output from {geode-name}: SBDG's Logback configuration defines three Loggers to control the log output from {geode-name}:
.{geode-name} Loggers by name .{geode-name} Loggers by Name
==== ====
[source,xml] [source,xml]
---- ----
@@ -135,24 +134,24 @@ SBDG's Logback configuration defines three Loggers to control the log output fro
---- ----
==== ====
The `com.gemstone.gemfire` logger is a legacy Logger that covers old GemFire bits that are still present in {geode-name} The `com.gemstone.gemfire` Logger covers old GemFire components that are still present in {geode-name} for backwards
for backwards compatibility. By default, it logs output at `INFO`. This logger's use should be largely unnecessary. compatibility. By default, it logs output at `INFO`. This Logger's use should be mostly unnecessary.
The `org.apache.geode` logger is the primary logger used to control log output from all {geode-name} components The `org.apache.geode` Logger is the primary Logger used to control log output from all {geode-name} components
during the runtime operation of {geode-name}. By default, it logs output at `INFO`. during the runtime operation of {geode-name}. By default, it logs output at `INFO`.
The `org.jgroups` logger is used to log output from {geode-name}'s message distribution and membership system. The `org.jgroups` logger is used to log output from {geode-name}'s message distribution and membership system.
{geode-name} uses JGroups for membership and message distribution between peer members (nodes) in the cluster {geode-name} uses JGroups for membership and message distribution between peer members (nodes) in the cluster
(distributed system). By default, JGroups logs output at `ERROR`. (distributed system). By default, JGroups logs output at `ERROR`.
You can configure the log level for the `com.gemstone.gemfire` and `org.apache.geode` loggers by setting the You can configure the log level for the `com.gemstone.gemfire` and `org.apache.geode` Loggers by setting
`spring.boot.data.gemfire.log.level` property. You can independently configure the `org.jgroups` logger by setting the the `spring.boot.data.gemfire.log.level` property. You can independently configure the `org.jgroups` Logger by setting
`spring.boot.data.gemfire.jgroups.log.level` property. the `spring.boot.data.gemfire.jgroups.log.level` property.
You can set the SBDG logging properties on the command line as JVM system properties when you run You can set the SBDG logging properties on the command line as JVM System properties when you run
your Spring Boot application: your Spring Boot application:
.Setting the log-level from the command-line .Setting the log-level from the CLI
==== ====
[source,text] [source,text]
---- ----
@@ -161,12 +160,13 @@ $ java -classpath ...:/path/to/MySpringBootApplication.jar -Dspring.boot.data.ge
---- ----
==== ====
NOTE: Setting JVM system properties by using `$ java -jar MySpringBootApplication.jar -Dspring.boot.data.gemfire.log.level=DEBUG` NOTE: Setting JVM System properties by using
`$ java -jar MySpringBootApplication.jar -Dspring.boot.data.gemfire.log.level=DEBUG`
is not supported by the Java Runtime Environment (JRE). is not supported by the Java Runtime Environment (JRE).
Alternatively, you can configure and control {geode-name} logging in Spring Boot `application.properties`: Alternatively, you can configure and control {geode-name} logging in Spring Boot `application.properties`:
.Setting the log-level in `application.properties` .Setting the log-level in Spring Boot `application.properties`
==== ====
[source,properties] [source,properties]
---- ----
@@ -174,9 +174,10 @@ spring.boot.data.gemfire.log.level=DEBUG
---- ----
==== ====
For backwards compatibility, SBDG additionally supports the old Spring Data for {geode-name} (SDG) logging properties For backwards compatibility, SBDG additionally supports the Spring Data for {geode-name} (SDG) logging properties
as well, by using either of the following properties: as well, by using either of the following properties:
.Setting log-level using SDG Properties
==== ====
[source,properties] [source,properties]
---- ----
@@ -185,16 +186,16 @@ spring.data.gemfire.logging.level=DEBUG
---- ----
==== ====
If you previously used either of these SDG-based logging properties, they continue to work as designed in If you previously used either of these SDG-based logging properties, they continue to work as designed in SBDG `1.3`
SBDG `1.3` or later. or later.
[[geode-logging-configuration-composition]] [[geode-logging-configuration-composition]]
==== Composing Logging Configuration ==== Composing Logging Configuration
As mentioned earlier, SBDG lets you compose your own logging configuration from SBDG's default Logback As mentioned earlier, SBDG lets you compose your own logging configuration from SBDG's default Logback configuration
configuration metadata. metadata.
SBDG conveniently bundles the loggers and appenders from SBDG's logging starter into a template file that you can SBDG conveniently bundles the Loggers and Appenders from SBDG's logging starter into a template file that you can
include into your own custom Logback XML configuration file. include into your own custom Logback XML configuration file.
The Logback template file appears as follows: The Logback template file appears as follows:
@@ -242,25 +243,28 @@ In addition to the `LogbackSupport` class, SBDG also provides some custom Logbac
[[geode-logging-slf4j-logback-api-support-appender-composite]] [[geode-logging-slf4j-logback-api-support-appender-composite]]
==== CompositeAppender ==== CompositeAppender
The `org.springframework.geode.logging.slf4j.logback.CompositeAppender` class is an implementation of Logback The `org.springframework.geode.logging.slf4j.logback.CompositeAppender` class is an implementation of the Logback
`Appender` and the https://en.wikipedia.org/wiki/Composite_pattern[composite software design pattern]. `Appender` interface and the https://en.wikipedia.org/wiki/Composite_pattern[Composite software design pattern].
`CompositeAppender` lets developers compose multiple appenders and use them as if they were a single `Appender`. `CompositeAppender` lets developers compose multiple Appenders and use them as if they were a single `Appender`.
For example, you could compose both the Logback `ConsoleAppender` and `FileAppender` into one appender: For example, you could compose both the Logback `ConsoleAppender` and `FileAppender` into one `Appender`:
.Composing multiple `Appenders` .Composing multiple `Appenders`
==== ====
[source,java] [source,java]
---- ----
class LoggingConfiguration { class LoggingConfiguration {
void composeApenders() {
Appender<ILoggingEvent> compositeAppender() {
ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>(); ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
FileAppender<ILoggingEvent> fileAppender = new FileApender<>(); FileAppender<ILoggingEvent> fileAppender = new FileApender<>();
Appender<ILoggingEvent> compositeAppender = CompositeAppender.compose(consoleAppender, fileAppender); Appender<ILoggingEvent> compositeAppender = CompositeAppender.compose(consoleAppender, fileAppender);
return compositeAppender;
} }
} }
@@ -268,13 +272,14 @@ class LoggingConfiguration {
---- ----
==== ====
You could then add the `CompositeAppender` to a "`named`" `Logger`: You could then add the `CompositeAppender` to a named `Logger`:
.Register `CompositeAppender` on "named" `Logger` .Register `CompositeAppender` on "named" `Logger`
==== ====
[source,java] [source,java]
---- ----
class LoggerConfiguration { class LoggerConfiguration {
void registerAppenderOnLogger() { void registerAppenderOnLogger() {
Logger namedLogger = LoggerFactory.getLogger("loggerName"); Logger namedLogger = LoggerFactory.getLogger("loggerName");
@@ -286,7 +291,7 @@ class LoggerConfiguration {
---- ----
==== ====
In this case, the "`named`" `Logger` logs events (or log messages) to both the console and file appenders. In this case, the named `Logger` logs events (or log messages) to both the console and file Appenders.
You can compose an array or `Iterable` of `Appenders` by using either the You can compose an array or `Iterable` of `Appenders` by using either the
`CompositeAppender.compose(:Appender<T>[])` method or the `CompositeAppender.compose(:Iterable<Appender<T>>)` method. `CompositeAppender.compose(:Appender<T>[])` method or the `CompositeAppender.compose(:Iterable<Appender<T>>)` method.
@@ -295,12 +300,12 @@ You can compose an array or `Iterable` of `Appenders` by using either the
==== DelegatingAppender ==== DelegatingAppender
The `org.springframework.geode.logging.slf4j.logback.DelegatingAppender` is a pass-through Logback `Appender` The `org.springframework.geode.logging.slf4j.logback.DelegatingAppender` is a pass-through Logback `Appender`
implementation that wraps another Logback `Appender` or collection of `Appenders`, such as the implementation that wraps another Logback `Appender` or collection of `Appenders`, such as the `ConsoleAppender`,
`ConsoleAppender`, a `FileAppender`, a `SocketAppender`, or others. By default, the `DelegatingAppender` delegates a `FileAppender`, a `SocketAppender`, or others. By default, the `DelegatingAppender` delegates to the `NOPAppender`,
to the `NOPAppender`, thereby doing no actual work. thereby doing no actual work.
By default, SBDG registers the `org.springframework.geode.logging.slfj4.logback.DelegatingAppender` with By default, SBDG registers the `org.springframework.geode.logging.slfj4.logback.DelegatingAppender` with the ROOT
the ROOT `Logger`, which can be useful for testing purposes. `Logger`, which can be useful for testing purposes.
With a reference to a `DelegatingAppender`, you can add any `Appender` (even a `CompositeAppender`) as the delegate: With a reference to a `DelegatingAppender`, you can add any `Appender` (even a `CompositeAppender`) as the delegate:
@@ -309,6 +314,7 @@ With a reference to a `DelegatingAppender`, you can add any `Appender` (even a `
[source,java] [source,java]
---- ----
class LoggerConfiguration { class LoggerConfiguration {
void setupDelegation() { void setupDelegation() {
ConsoleAppender consoleAppender = new ConsoleAppender(); ConsoleAppender consoleAppender = new ConsoleAppender();
@@ -331,12 +337,12 @@ class LoggerConfiguration {
[[geode-logging-slf4j-logback-api-support-appender-string]] [[geode-logging-slf4j-logback-api-support-appender-string]]
==== StringAppender ==== StringAppender
The `org.springframework.geode.logging.slf4j.logback.StringAppender` stores log message in-memory, appended to The `org.springframework.geode.logging.slf4j.logback.StringAppender` stores a log message in-memory, appended to
a `String`. a `String`.
The `StringAppender` is useful for testing purposes. For instance, you can use the `StringAppender` to assert that The `StringAppender` is useful for testing purposes. For instance, you can use the `StringAppender` to assert that
a `Logger` used by certain application components logged messages at the appropriately configured log level while other a `Logger` used by certain application components logged messages at the appropriately configured log level
log messages were not logged. while other log messages were not logged.
Consider the following example: Consider the following example:
@@ -398,7 +404,7 @@ class ApplicationComponentUnitTests {
---- ----
==== ====
There are many other uses for the `StringAppender` and you can use it safely in a multi-threaded context by calling There are many other uses for the `StringAppender` and you can use it safely in a multi-Threaded context by calling
`StringAppender.Builder.useSynchronization()`. `StringAppender.Builder.useSynchronization()`.
When combined with other SBDG provided `Appenders` in conjunction with the `LogbackSupport` class, you have a lot of When combined with other SBDG provided `Appenders` in conjunction with the `LogbackSupport` class, you have a lot of

View File

@@ -5,23 +5,27 @@
Using Spring Data Repositories with {geode-name} makes short work of data access operations when you use {geode-name} Using Spring Data Repositories with {geode-name} makes short work of data access operations when you use {geode-name}
as your System of Record (SoR) to persist your application's state. as your System of Record (SoR) to persist your application's state.
{spring-data-commons-docs-html}/#repositories[Spring Data repositories] provide a convenient and powerful way Using Spring Data Repositories with {geode-name} makes short work of data access operations when you use {geode-name}
to define basic CRUD and simple query data access operations by specifying the contract of those data access as your System of Record (SoR) to persist your application's state.
operations in a Java interface.
Spring Boot for {geode-name} auto-configures the Spring Data for {geode-name} {spring-data-geode-docs-html}/#gemfire-repositories[repository extension] {spring-data-commons-docs-html}/#repositories[Spring Data Repositories] provide a convenient and powerful way to define
when either is declared on your application's classpath. You need not do anything special to enable it. You can basic CRUD and simple query data access operations by specifying the contract of those data access operations in a Java
start coding your application-specific Repository interfaces. interface.
The following example defines a `Customer` class to model customers and map it to the {geode-name} `Customers` region by using the SDG Spring Boot for {geode-name} auto-configures the Spring Data for {geode-name}
{spring-data-geode-javadoc}/org/springframework/data/gemfire/mapping/annotation/Region.html[`@Region`] mapping {spring-data-geode-docs-html}/#gemfire-repositories[Repository extension]
annotation: when either is declared on your application's classpath. You need not do anything special to enable it. You can start
coding your application-specific Repository interfaces.
The following example defines a `Customer` class to model customers and map it to the {geode-name} `Customers` Region
by using the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/mapping/annotation/Region.html[`@Region`]
mapping annotation:
.`Customer` entity class .`Customer` entity class
==== ====
[source,java] [source,java]
---- ----
package example.app.books.model; package example.app.crm.model;
@Region("Customers") @Region("Customers")
class Customer { class Customer {
@@ -35,13 +39,14 @@ class Customer {
---- ----
==== ====
The following example shows how to declare your repository (a.k.a. {wikipedia-docs}/Data_access_object[Data Access Object (DAO)]) for `Customers`: The following example shows how to declare your Repository (a.k.a. {wikipedia-docs}/Data_access_object[Data Access Object (DAO)])
for `Customers`:
.`CustomerRepository` for peristing and accessing `Customers` .`CustomerRepository` for peristing and accessing `Customers`
==== ====
[source,java] [source,java]
---- ----
package example.app.books.repo; package example.app.crm.repo;
interface CustomerRepository extends CrudRepository<Customer, Long> { interface CustomerRepository extends CrudRepository<Customer, Long> {
@@ -80,6 +85,6 @@ class SpringBootApacheGeodeClientCacheApplication {
---- ----
==== ====
See Spring Data Commons' {spring-data-commons-docs-html}/#repositories[repositories abstraction] See Spring Data Commons' {spring-data-commons-docs-html}/#repositories[Repositories abstraction]
and Spring Data for {geode-name}'s {spring-data-geode-docs-html}/#gemfire-repositories[repositories extension] and Spring Data for {geode-name}'s {spring-data-geode-docs-html}/#gemfire-repositories[Repositories extension]
for more detail. for more detail.

View File

@@ -5,17 +5,16 @@
This section contains working examples that show how to use Spring Boot for {geode-name} (SBDG) effectively. This section contains working examples that show how to use Spring Boot for {geode-name} (SBDG) effectively.
Some examples focus on specific use cases (such as (HTTP) session state caching), while other examples show how Some examples focus on specific use cases (such as (HTTP) session state caching), while other examples show how SBDG
SBDG works under the hood, to give you a better understanding of what is actually happening and how to debug problems works under the hood, to give you a better understanding of what is actually happening and how to debug problems with
with your {geode-name}, Spring Boot applications. your Spring Boot {geode-name} applications.
.Example Spring Boot applications using {geode-name} .Example Spring Boot applications using {geode-name}
|=== |===
| Guide | Description | Source | Guide | Description | Source
| link:guides/getting-started.html[Getting Started with Spring Boot for {geode-name}] | link:guides/getting-started.html[Getting Started with Spring Boot for {geode-name}]
| Explains how to get started quickly, easily, and reliably building {geode-name} and Pivotal Cloud Cache-powered | Explains how to get started quickly, easily, and reliably building {geode-name} powered applications with Spring Boot.
applications with Spring Boot.
| {github-samples-url}/intro/getting-started[Getting Started] | {github-samples-url}/intro/getting-started[Getting Started]
| link:guides/boot-configuration.html[Spring Boot Auto-Configuration for {geode-name}] | link:guides/boot-configuration.html[Spring Boot Auto-Configuration for {geode-name}]
@@ -27,37 +26,36 @@ applications with Spring Boot.
| {github-samples-url}/boot/actuator[Spring Boot Actuator] | {github-samples-url}/boot/actuator[Spring Boot Actuator]
| link:guides/boot-security.html[Spring Boot Security for {geode-name}] | link:guides/boot-security.html[Spring Boot Security for {geode-name}]
| Explains how to configure auth and TLS with SSL when you use {geode-name} and Pivotal Cloud Cache | Explains how to configure auth and TLS with SSL when you use {geode-name} in your Spring Boot applications.
in Spring Boot applications.
| {github-samples-url}/boot/security[Spring Boot Security] | {github-samples-url}/boot/security[Spring Boot Security]
| link:guides/caching-look-aside.html[Look-Aside Caching with Spring's Cache Abstraction and {geode-name}] | link:guides/caching-look-aside.html[Look-Aside Caching with Spring's Cache Abstraction and {geode-name}]
| Explains how to enable and use the Spring Cache Abstraction with {geode-name} as the caching provider for look-aside caching. | Explains how to enable and use Spring's Cache Abstraction with {geode-name} as the caching provider
for look-aside caching.
| {github-samples-url}/caching/look-aside[Look-Aside Caching] | {github-samples-url}/caching/look-aside[Look-Aside Caching]
| link:guides/caching-inline.html[Inline Caching with Spring's Cache Abstraction and {geode-name}] | link:guides/caching-inline.html[Inline Caching with Spring's Cache Abstraction and {geode-name}]
| Explains how to enable and use the Spring cache abstraction with {geode-name} as the caching provider for inline caching. | Explains how to enable and use Spring's Cache Abstraction with {geode-name} as the caching provider for inline caching.
This sample builds on the look-aside caching sample, described earlier. This sample builds on the look-aside caching sample.
| {github-samples-url}/caching/inline[Inline Caching] | {github-samples-url}/caching/inline[Inline Caching]
| link:guides/caching-inline-async.html[Asynchronous Inline Caching with Spring's Cache Abstraction and {geode-name}] | link:guides/caching-inline-async.html[Asynchronous Inline Caching with Spring's Cache Abstraction and {geode-name}]
| Explains how to enable and use the Spring cache abstraction with {geode-name} as the caching provider for asynchronous | Explains how to enable and use Spring's Cache Abstraction with {geode-name} as the caching provider for asynchronous
inline caching. This sample builds on the look-aside caching and inline caching samples, described earlier. inline caching. This sample builds on the look-aside and inline caching samples.
| {github-samples-url}/caching/inline-async[Asynchronous Inline Caching] | {github-samples-url}/caching/inline-async[Asynchronous Inline Caching]
| link:guides/caching-near.html[Near Caching with Spring's Cache Abstraction and {geode-name}] | link:guides/caching-near.html[Near Caching with Spring's Cache Abstraction and {geode-name}]
| Explains how to enable and use the Spring cache abstraction with {geode-name} as the caching provider for near caching. | Explains how to enable and use Spring's Cache Abstraction with {geode-name} as the caching provider for near caching.
This sample builds on the look-aside caching sample, described earlier. This sample builds on the look-aside caching sample.
| {github-samples-url}/caching/near[Near Caching] | {github-samples-url}/caching/near[Near Caching]
| link:guides/caching-multi-site.html[Multi-Site Caching with Spring's Cache Abstraction and {geode-name}] | link:guides/caching-multi-site.html[Multi-Site Caching with Spring's Cache Abstraction and {geode-name}]
| Explains how to enable and use the Spring cache abstraction with {geode-name} as the caching provider for multi-site caching. | Explains how to enable and use Spring's Cache Abstraction with {geode-name} as the caching provider for multi-site
This sample builds on the look-aside caching sample, described earlier, and is the fourth and final leg in our study caching. This sample builds on the look-aside caching sample.
of caching patterns.
| {github-samples-url}/caching/multi-site[Multi-Site Caching] | {github-samples-url}/caching/multi-site[Multi-Site Caching]
| link:guides/caching-http-session.html[HTTP Session Caching with Spring Session and {geode-name}] | link:guides/caching-http-session.html[HTTP Session Caching with Spring Session and {geode-name}]
| Explains how to enable and use Spring Session with {geode-name} to manage HTTP Session state. | Explains how to enable and use Spring Session with {geode-name} to manage HTTP session state.
| {github-samples-url}/caching/http-session[HTTP Session Caching] | {github-samples-url}/caching/http-session[HTTP Session Caching]
|=== |===

View File

@@ -5,6 +5,9 @@
This sections covers security configuration for {geode-name}, which includes both authentication and authorization This sections covers security configuration for {geode-name}, which includes both authentication and authorization
(collectively, auth) as well as Transport Layer Security (TLS) using SSL. (collectively, auth) as well as Transport Layer Security (TLS) using SSL.
This chapter covers security configuration for {geode-name}, which includes both authentication and authorization
(collectively, auth) as well as Transport Layer Security (TLS) using SSL.
NOTE: Securing data at rest is not supported by {geode-name}. NOTE: Securing data at rest is not supported by {geode-name}.
TIP: See the corresponding sample link:guides/boot-security.html[guide] and {github-samples-url}/boot/security[code] TIP: See the corresponding sample link:guides/boot-security.html[guide] and {github-samples-url}/boot/security[code]
@@ -14,28 +17,29 @@ to see Spring Boot Security for {geode-name} in action.
=== Authentication and Authorization === Authentication and Authorization
{geode-name} employs username- and password-based {apache-geode-docs}/managing/security/authentication_overview.html[authentication] {geode-name} employs username- and password-based {apache-geode-docs}/managing/security/authentication_overview.html[authentication]
and role-based {apache-geode-docs}/managing/security/authorization_overview.html[authorization] to secure and role-based {apache-geode-docs}/managing/security/authorization_overview.html[authorization] to secure your client to
your client to server data exchanges and operations. server data exchanges and operations.
Spring Data for {geode-name} provides {spring-data-geode-docs-html}/#bootstrap-annotation-config-security[first-class support] Spring Data for {geode-name} provides {spring-data-geode-docs-html}/#bootstrap-annotation-config-security[first-class support]
for {geode-name}'s Security framework, which is based on the for {geode-name}'s Security framework, which is based on the
{apache-geode-javadoc}/org/apache/geode/security/SecurityManager.html[`SecurityManager`] interface. {apache-geode-javadoc}/org/apache/geode/security/SecurityManager.html[`SecurityManager`] interface.
Additionally, {geode-name}'s Security framework is integrated with https://shiro.apache.org/[Apache Shiro]. Additionally, {geode-name}'s Security framework is integrated with https://shiro.apache.org/[Apache Shiro].
NOTE: Eventually, SBDG will also provide support for and integration with https://spring.io/projects/spring-security[Spring Security]. NOTE: SBDG will eventually provide support for and integration with
https://spring.io/projects/spring-security[Spring Security].
When you use Spring Boot for {geode-name}, which builds on the bits provided in Spring Data for {geode-name}, When you use Spring Boot for {geode-name}, which builds Spring Data for {geode-name}, it makes short work of
it makes short work of enabling auth in both your clients and servers. enabling auth in both your clients and servers.
[[geode-security-auth-servers]] [[geode-security-auth-servers]]
==== Auth for Servers ==== Auth for Servers
The easiest and most standard way to enable auth in the servers of your cluster is to simply define one or more The easiest and most standard way to enable auth in the servers of your cluster is to simply define one or more
Apache Shiro https://shiro.apache.org/realm.html[realms] as beans in the Spring `ApplicationContext`. Apache Shiro https://shiro.apache.org/realm.html[Realms] as beans in the Spring `ApplicationContext`.
Consider the following example: Consider the following example:
.Declaring an Apache Shiro realm .Declaring an Apache Shiro Realm
==== ====
[source,java] [source,java]
---- ----
@@ -52,10 +56,9 @@ class ApacheGeodeSecurityConfiguration {
---- ----
==== ====
When an Apache Shiro realm (such as `DefaultLdapRealm`) is declared and registered in the Spring `ApplicationContext` as a When an Apache Shiro Realm (such as `DefaultLdapRealm`) is declared and registered in the Spring `ApplicationContext`
Spring bean, Spring Boot automatically detects this `Realm` bean (or `Realm` beans if more than one is configured), as a Spring bean, Spring Boot automatically detects this `Realm` bean (or `Realm` beans if more than one is configured),
and the {geode-name} servers in the cluster are automatically configured with authentication and authorization and the servers in the {geode-name} cluster are automatically configured with authentication and authorization enabled.
enabled.
Alternatively, you can provide a custom, application-specific implementation of {geode-name}'s Alternatively, you can provide a custom, application-specific implementation of {geode-name}'s
{apache-geode-javadoc}/org/apache/geode/security/SecurityManager.html[`SecurityManager`] interface, {apache-geode-javadoc}/org/apache/geode/security/SecurityManager.html[`SecurityManager`] interface,
@@ -78,27 +81,28 @@ class ApacheGeodeSecurityConfiguration {
---- ----
==== ====
Spring Boot discovers your custom, application-specific `SecurityManager` implementation and configures Spring Boot discovers your custom, application-specific `SecurityManager` implementation and configures the servers
the servers in the {geode-name} cluster with authentication and authorization enabled. in the {geode-name} cluster with authentication and authorization enabled.
TIP: The Spring team recommends that you use Apache Shiro to manage the authentication and authorization of your TIP: The Spring team recommends that you use Apache Shiro to manage the authentication and authorization of your
{geode-name} servers over implementing {geode-name}'s `SecurityManager` interface. servers over implementing {geode-name}'s `SecurityManager` interface.
[[geode-security-auth-clients]] [[geode-security-auth-clients]]
==== Auth for Clients ==== Auth for Clients
When {geode-name} servers have been configured with authentication and authorization enabled, clients must When servers in an {geode-name} cluster have been configured with authentication and authorization enabled, clients
authenticate when connecting. must authenticate when connecting.
Spring Boot for {geode-name} makes this easy, regardless of whether you run your Spring Boot `ClientCache` Spring Boot for {geode-name} makes this easy, regardless of whether you run your Spring Boot `ClientCache` applications
applications in a local, non-managed environment or run in a cloud-managed environment. in a local, non-managed environment or run in a cloud-managed environment.
[[geode-security-auth-clients-non-managed]] [[geode-security-auth-clients-non-managed]]
===== Non-Managed Auth for Clients ===== Non-Managed Auth for Clients
To enable Auth for clients that connect to a secure {geode-name} cluster, you need only set a username To enable auth for clients that connect to a secure {geode-name} cluster, you need only set a username and password
and password in your Spring Boot `application.properties` file: in Spring Boot `application.properties`:
.Spring Boot `application.properties` for the client
==== ====
[source,txt] [source,txt]
---- ----
@@ -114,21 +118,22 @@ Spring Boot for {geode-name} handles the rest.
[[geode-secuirty-auth-clients-managed]] [[geode-secuirty-auth-clients-managed]]
===== Managed Auth for Clients ===== Managed Auth for Clients
Enabling auth for clients that connect to a Pivotal Cloud Cache (PCC) service instance in Pivotal CloudFoundry (PCF) Enabling auth for clients that connect to a {pivotal-cloudcache-name} service instance (PCC)
is even easier: You need do nothing. in {pivotal-cloudfoundry-name} (PCF) is even easier: You need do nothing.
If your Spring Boot application uses SBDG and is bound to PCC, when you push (that is, deploy) your app to PCF, If your Spring Boot application uses SBDG and is bound to PCC, when you deploy (that is, `cf push`) your application
Spring Boot for {geode-name} extracts the required auth credentials from the environment that you set up when you to PCF, Spring Boot for {geode-name} extracts the required auth credentials from the environment that you set up when
provisioned a PCC service instance in your PCF organization and space. PCC automatically assigns two users with roles of you provisioned a PCC service instance in your PCF organization and space. PCC automatically assigns two users with
`cluster_operator` and `developer`, respectively, to any Spring Boot application bound to the PCC service instance. roles of `cluster_operator` and `developer`, respectively, to any Spring Boot application bound to the PCC service
instance.
By default, SBDG auto-configures your Spring Boot application to run with the user that has the `cluster_operator` role. By default, SBDG auto-configures your Spring Boot application to run with the user that has the `cluster_operator` role.
This ensures that your Spring Boot application has the necessary permissions (authorization) to perform all data access This ensures that your Spring Boot application has the necessary permission (authorization) to perform all data access
operations on the servers in the PCC cluster, including, for example, pushing configuration metadata from the client operations on the servers in the PCC cluster, including, for example, pushing configuration metadata from the client
to the servers in the PCC cluster. to the servers in the PCC cluster.
See the <<cloudfoundry-cloudcache-security-auth-runtime-user-configuration,Running Spring Boot applications as a specific user>> section See the <<cloudfoundry-cloudcache-security-auth-runtime-user-configuration,Running Spring Boot applications as a specific user>> section
in the <<cloudfoundry,Pivotal Cloud Foundry>> chapter for additional details on user authentication and authorization. in the <<cloudfoundry,Pivotal CloudFoundry>> chapter for additional details on user authentication and authorization.
See the <<cloudfoundry,chapter>> (titled "`Pivotal CloudFoundry`") for more general details. See the <<cloudfoundry,chapter>> (titled "`Pivotal CloudFoundry`") for more general details.
@@ -138,14 +143,14 @@ when you use PCC and PCF.
[[geode-security-ssl]] [[geode-security-ssl]]
=== Transport Layer Security using SSL === Transport Layer Security using SSL
Securing data in motion is also essential to the integrity of your application. Securing data in motion is also essential to the integrity of your Spring [Boot] applications.
For instance, it would not do much good to send usernames and passwords over plain text socket connections For instance, it would not do much good to send usernames and passwords over plain text socket connections
between your clients and servers nor to send sensitive data over those same connections. between your clients and servers nor to send other sensitive data over those same connections.
Therefore, {geode-name} supports SSL between clients and servers, between JMX clients (such as Gfsh) and the manager, Therefore, {geode-name} supports SSL between clients and servers, between JMX clients (such as Gfsh) and the Manager,
between HTTP clients when you use the developer REST API or Pulse, between peers in the cluster, and when you use the WAN Gateway between HTTP clients when you use the Developer REST API or Pulse, between peers in the cluster, and when you use
to connect multiple sites (that is, clusters). the WAN Gateway to connect multiple sites (clusters).
Spring Data for {geode-name} provides Spring Data for {geode-name} provides
https://docs.spring.io/spring-data/geode/docs/current/reference/html/#bootstrap-annotation-config-ssl[first-class support] https://docs.spring.io/spring-data/geode/docs/current/reference/html/#bootstrap-annotation-config-ssl[first-class support]
@@ -153,10 +158,10 @@ for configuring and enabling SSL as well. Still, Spring Boot makes it even easie
especially during development. especially during development.
{geode-name} requires certain properties to be configured. These properties translate to the appropriate {geode-name} requires certain properties to be configured. These properties translate to the appropriate
`javax.net.ssl.*` properties required by the JRE to create Secure Socket Connections by using `javax.net.ssl.*` properties required by the JRE to create secure socket connections by using
https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html[JSSE]. https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html[JSSE].
However,, ensuring that you have set all the required SSL properties correctly is an error prone and tedious task. However, ensuring that you have set all the required SSL properties correctly is an error prone and tedious task.
Therefore, Spring Boot for {geode-name} applies some basic conventions for you. Therefore, Spring Boot for {geode-name} applies some basic conventions for you.
You can create a `trusted.keystore` as a JKS-based `KeyStore` file and place it in one of three well-known locations: You can create a `trusted.keystore` as a JKS-based `KeyStore` file and place it in one of three well-known locations:
@@ -168,7 +173,7 @@ You can create a `trusted.keystore` as a JKS-based `KeyStore` file and place it
When this file is named `trusted.keystore` and is placed in one of these three well-known locations, Spring Boot When this file is named `trusted.keystore` and is placed in one of these three well-known locations, Spring Boot
for {geode-name} automatically configures your client to use SSL socket connections. for {geode-name} automatically configures your client to use SSL socket connections.
You can use Spring Boot to configure and bootstrap an {geode-name} server: If you use Spring Boot to configure and bootstrap an {geode-name} server:
.Spring Boot configured and bootstrapped {geode-name} server .Spring Boot configured and bootstrapped {geode-name} server
==== ====
@@ -196,14 +201,14 @@ If your `trusted.keystore` file is secured with a password, you need to addition
---- ----
# Spring Boot application.properties # Spring Boot application.properties
spring.data.gemfire.security.ssl.keystore.password = p@55w0rd! spring.data.gemfire.security.ssl.keystore.password=p@55w0rd!
---- ----
==== ====
You can also configure the location of the keystore and truststore files, if they are separate and have not been placed You can also configure the location of the keystore and truststore files, if they are separate and have not been placed
in one of the default, well-known locations searched by Spring Boot: in one of the default, well-known locations searched by Spring Boot:
.Accessing a secure `trusted.keystore` .Accessing a secure `trusted.keystore` by location
==== ====
[source,txt] [source,txt]
---- ----
@@ -222,11 +227,11 @@ annotation for all the configuration attributes and the corresponding properties
[[geode-security-encryption]] [[geode-security-encryption]]
=== Securing Data at Rest === Securing Data at Rest
Currently, neither {geode-name} nor Spring Boot nor Spring Data for {geode-name} offer any support for securing your data Currently, neither {geode-name} nor Spring Boot nor Spring Data for {geode-name} offer any support for securing your
while at rest (for example, when your data has been overflowed or persisted to disk). data while at rest (for example, when your data has been overflowed or persisted to disk).
To secure data at rest when using {geode-name}, with or without Spring, you must employ third-party solutions, such as disk To secure data at rest when using {geode-name}, with or without Spring, you must employ third-party solutions, such as
encryption, which is usually highly contextual and technology-specific. disk encryption, which is usually highly contextual and technology-specific.
For example, to secure data at rest when you use Amazon EC2, see For example, to secure data at rest when you use Amazon EC2, see
https://aws.amazon.com/blogs/security/how-to-protect-data-at-rest-with-amazon-ec2-instance-store-encryption/[Instance Store Encryption]. https://aws.amazon.com/blogs/security/how-to-protect-data-at-rest-with-amazon-ec2-instance-store-encryption/[Instance Store Encryption].

View File

@@ -1,37 +1,37 @@
[[geode-session]] [[geode-session]]
== Spring Session == Spring Session
:geode-name: {apache-geode-name} :geode-name: {apache-geode-name}
:pcc-name: Pivotal Cloud Cache :pcc-name: {pivotal-cloudcache-name}
:vmw-tas-name: VMware Tanzu Application Service :vmw-tas-name: {pivotal-cloudfoundry-name}
This chapter covers auto-configuration of Spring Session with {geode-name} to manage (HTTP) session state in a reliable This chapter covers auto-configuration of Spring Session for {geode-name} to manage (HTTP) session state in a reliable
(consistent), highly available (replicated), and clustered manner. (consistent), highly available (replicated), and clustered manner.
{spring-session-website}[Spring Session] provides an API and several implementations for managing a user's session {spring-session-website}[Spring Session] provides an API and several implementations for managing a user's session
information. It has the ability to replace the `javax.servlet.http.HttpSession` in an application container-neutral information. It has the ability to replace the `javax.servlet.http.HttpSession` in an application container-neutral way
way and provide session IDs in HTTP headers to work with RESTful APIs. and provide session IDs in HTTP headers to work with RESTful APIs.
Furthermore, Spring Session provides the ability to keep the HttpSession alive even when working with WebSockets Furthermore, Spring Session provides the ability to keep the `HttpSession` alive even when working with `WebSockets`
and reactive Spring WebFlux WebSessions. and reactive Spring WebFlux `WebSessions`.
A full discussion of Spring Session is beyond the scope of this document. You can learn more A complete discussion of Spring Session is beyond the scope of this document. You can learn more by reading
by reading the {spring-session-docs}[docs] and reviewing the {spring-session-docs}/#samples[samples]. the {spring-session-docs}[docs] and reviewing the {spring-session-docs}/#samples[samples].
Spring Boot for {geode-name} provides auto-configuration support to configure {geode-name} Spring Boot for {geode-name} provides auto-configuration support to configure {geode-name} as the session management
as the user's session information management provider and store when {spring-session-data-gemfire-website}[Spring Session for {geode-name}] provider and store when {spring-session-data-gemfire-website}[Spring Session for {geode-name}] is on your Spring Boot
is on your Spring Boot application's classpath. application's classpath.
TIP: You can learn more about Spring Session for {geode-name} in the {spring-session-data-gemfire-docs}[docs]. TIP: You can learn more about Spring Session for {geode-name} in the {spring-session-data-gemfire-docs}[docs].
TIP: See the corresponding sample link:guides/caching-http-session.html.html[guide] and {github-samples-url}/caching/http-session[code] TIP: See the corresponding sample link:guides/caching-http-session.html.html[guide]
to see Spring Session for {geode-name} in action. and {github-samples-url}/caching/http-session[code] to see Spring Session for {geode-name} in action.
[[geode-session-configuration]] [[geode-session-configuration]]
=== Configuration === Configuration
You need do nothing special to use {geode-name} as a Spring Session provider, You need do nothing special to use {geode-name} as a Spring Session provider implementation, managing the (HTTP) session
managing the (HTTP) session state of your Spring Boot application. state of your Spring Boot application.
To do so, include the appropriate Spring Session dependency on your Spring Boot application's classpath: To do so, include the appropriate Spring Session dependency on your Spring Boot application's classpath:
@@ -82,10 +82,10 @@ public class MySpringBootApplication {
---- ----
==== ====
You can then create application-specific Spring Web MVC `Controllers` to interact with the `HttpSession` You can then create application-specific Spring Web MVC `Controllers` to interact with the `HttpSession` as needed
as needed by your application: by your application:
.Application Controller using HttpSession .Spring Boot Application `Controller` using `HttpSession`
==== ====
[source,java] [source,java]
---- ----
@@ -105,16 +105,18 @@ The `HttpSession` is replaced by a Spring managed `Session` that is stored in {g
[[geode-session-configuration-custom]] [[geode-session-configuration-custom]]
=== Custom Configuration === Custom Configuration
By default, Spring Boot for {geode-name} (SBDG) applies reasonable and sensible defaults when configuring By default, Spring Boot for {geode-name} (SBDG) applies reasonable and sensible defaults when configuring {geode-name}
{geode-name} as the provider in Spring Session. as the provider in Spring Session.
For instance, by default, SBDG sets the session expiration timeout to 30 minutes. It also uses a For instance, by default, SBDG sets the session expiration timeout to 30 minutes. It also uses a
`ClientRegionShortcut.PROXY` as the client Region data management policy for the {geode-name} `ClientRegionShortcut.PROXY` as the data management policy for the {geode-name} client Region that managing the (HTTP)
region that manages the (HTTP) Session state when the Spring Boot application is using a `ClientCache`, which it does session state when the Spring Boot application is using a `ClientCache`, which it does
by <<geode-clientcache-applications,default>>. by <<geode-clientcache-applications,default>>.
However, what if the defaults are not sufficient for your application requirements? In that case, see the next section. However, what if the defaults are not sufficient for your application requirements? In that case, see the next section.
In that case, see the next section.
[[geode-session-configuration-custom-properties]] [[geode-session-configuration-custom-properties]]
==== Custom Configuration using Properties ==== Custom Configuration using Properties
@@ -123,16 +125,16 @@ Spring Session for {geode-name} publishes
for each of the various Spring Session configuration options when you use {geode-name} as the (HTTP) session state for each of the various Spring Session configuration options when you use {geode-name} as the (HTTP) session state
management provider. management provider.
You can specify any of these properties in a Spring Boot `application.properties` file to adjust Spring Session's You can specify any of these properties in Spring Boot `application.properties` to adjust Spring Session's configuration
configuration when using {geode-name}. when using {geode-name}.
In addition to the properties provided in and by Spring Session for {geode-name}, Spring Boot for {geode-name} In addition to the properties provided in and by Spring Session for {geode-name}, Spring Boot for {geode-name} also
also recognizes and respects the `spring.session.timeout` property and the `server.servlet.session.timeout` recognizes and respects the `spring.session.timeout` property and the `server.servlet.session.timeout` property, as
property, as discussed {spring-boot-docs-html}/boot-features-session.html[the Spring Boot documentation]. discussed {spring-boot-docs-html}/boot-features-session.html[the Spring Boot documentation].
TIP: `spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds` takes precedence over TIP: `spring.session.data.gemfire.session.expiration.max-inactive-interval-seconds` takes precedence over
`spring.session.timeout`, which takes precedence over `server.servlet.session.timeout` when any combination `spring.session.timeout`, which takes precedence over `server.servlet.session.timeout` when any combination of
of these properties have been simultaneously configured in the Spring `Environment` of your application. these properties have been simultaneously configured in the Spring `Environment` of your application.
[[geode-session-configuration-custom-configurer]] [[geode-session-configuration-custom-configurer]]
==== Custom Configuration using a Configurer ==== Custom Configuration using a Configurer
@@ -142,9 +144,8 @@ Spring Session for {geode-name} also provides the
callback interface, which you can declare in your Spring `ApplicationContext` to programmatically control callback interface, which you can declare in your Spring `ApplicationContext` to programmatically control
the configuration of Spring Session when you use {geode-name}. the configuration of Spring Session when you use {geode-name}.
The `SpringSessionGemFireConfigurer`, when declared in the Spring `ApplicationContext`, takes precedence over any of the The `SpringSessionGemFireConfigurer`, when declared in the Spring `ApplicationContext`, takes precedence over any of
Spring Session (for {geode-name}) configuration properties and effectively overrides them when both the Spring Session (for {geode-name}) configuration properties and effectively overrides them when both are present.
are present.
More information on using the `SpringSessionGemFireConfigurer` can be found in the More information on using the `SpringSessionGemFireConfigurer` can be found in the
{spring-session-data-gemfire-docs}/#httpsession-gemfire-configuration-configurer[docs]. {spring-session-data-gemfire-docs}/#httpsession-gemfire-configuration-configurer[docs].
@@ -152,15 +153,18 @@ More information on using the `SpringSessionGemFireConfigurer` can be found in t
[[geode-session-disable]] [[geode-session-disable]]
=== Disabling Session State Caching === Disabling Session State Caching
There may be cases where you do not want your Spring Boot application to manage (HTTP) Session state by using {geode-name}. There may be cases where you do not want your Spring Boot application to manage (HTTP) session state by using
In certain cases, you may be using another Spring Session provider, such as Redis, to cache and manage your Spring Boot {geode-name}.
application's (HTTP) Session state. In other cases, you do not want to use Spring Session to manage your
(HTTP) Session state at all. Rather, you prefer to use your Web Server's (such as Tomcat's) `HttpSession` state management.
Either way, you can specifically call out your Spring Session provider by using the `spring.session.store-type` property In certain cases, you may be using another Spring Session provider implementation, such as Redis, to cache and manage
in `application.properties`: your Spring Boot application's (HTTP) session state. In other cases, you do not want to use Spring Session to manage
your (HTTP) session state at all. Rather, you prefer to use your Web Server's (such as Tomcat's) built-in `HttpSession`
state management capabilities.
.Use Redis as the Spring Session Provider Either way, you can specifically call out your Spring Session provider implementation by using
the `spring.session.store-type` property in Spring Boot `application.properties`:
.Use Redis as the Spring Session Provider Implementation
==== ====
[source,txt] [source,txt]
---- ----
@@ -171,8 +175,8 @@ spring.session.store-type=redis
---- ----
==== ====
If you prefer not to use Spring Session to manage your Spring Boot application's (HTTP) Session state at all, you can If you prefer not to use Spring Session to manage your Spring Boot application's (HTTP) session state at all, you can do
do the following: the following:
.Use Web Server Session State Management .Use Web Server Session State Management
==== ====
@@ -185,11 +189,11 @@ spring.session.store-type=none
---- ----
==== ====
Again, see the Spring Boot {spring-boot-docs-html}/boot-features-session.html[documetation] for more detail. Again, see the Spring Boot {spring-boot-docs-html}/boot-features-session.html[documentation] for more detail.
TIP: You can include multiple providers on the classpath of your Spring Boot application. For instance, TIP: You can include multiple provider implementations on the classpath of your Spring Boot application. For instance,
you might use Redis to cache your application's (HTTP) Session state while using {geode-name} as your you might use Redis to cache your application's (HTTP) session state while using {geode-name} as your application's
application's persistent store (system of record). transactional persistent store (System of Record).
NOTE: Spring Boot does not properly recognize `spring.session.store-type=[gemfire|geode]` even though NOTE: Spring Boot does not properly recognize `spring.session.store-type=[gemfire|geode]` even though
Spring Boot for {geode-name} is set up to handle either of these property values Spring Boot for {geode-name} is set up to handle either of these property values
@@ -198,16 +202,16 @@ Spring Boot for {geode-name} is set up to handle either of these property values
[[geode-session-pcc]] [[geode-session-pcc]]
=== Using Spring Session with {pcc-name} (PCC) === Using Spring Session with {pcc-name} (PCC)
Whether you use Spring Session in a Spring Boot `ClientCache` application to connect to an externally managed Whether you use Spring Session in a Spring Boot, {geode-name} `ClientCache` application to connect to an standalone,
cluster of {geode-name} servers or to connect to a cluster of servers in a {pcc-name} service instance managed by externally managed cluster of {geode-name} servers or to connect to a cluster of servers in a {pcc-name} service
a {vmw-tas-name} (TAS) environment, the setup is the same. instance managed by a {vmw-tas-name} environment, the setup is the same.
Spring Session for {geode-name} expects there to be a cache region in the cluster that can store and manage (HTTP) Spring Session for {geode-name} expects there to be a cache Region in the cluster that can store and manage (HTTP)
Session state when your Spring Boot application is a `ClientCache` application in a client/server topology. session state when your Spring Boot application is a `ClientCache` application in the client/server topology.
By default, the cache region used to store and manage (HTTP) Session state is called `ClusteredSpringSessions`. By default, the cache Region used to store and manage (HTTP) session state is called `ClusteredSpringSessions`.
We recommend that you configure the cache region name by using the well-known and documented property We recommend that you configure the cache Region name by using the well-known and documented property
in Spring Boot `application.properties`: in Spring Boot `application.properties`:
.Using properties .Using properties
@@ -218,8 +222,8 @@ spring.session.data.gemfire.session.region.name=MySessions
---- ----
==== ====
Alternatively, you can set the name of the cache region used to store and manage (HTTP) Session state by explicitly declaring Alternatively, you can set the name of the cache Region used to store and manage (HTTP) session state by explicitly
the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class: declaring the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class:
.Using `@EnableGemfireHttpSession .Using `@EnableGemfireHttpSession
==== ====
@@ -233,17 +237,17 @@ class MySpringBootSpringSessionApplication {
---- ----
==== ====
Once you decide on the cache region name used to store and manage (HTTP) Sessions, you must create the region in the Once you decide on the cache Region name used to store and manage (HTTP) sessions, you must create the cache Region
cluster somehow. in the cluster somehow.
On the client, doing so is simple, since SBDG's auto-configuration automatically creates the client `PROXY` region On the client, doing so is simple, since SBDG's auto-configuration automatically creates the client `PROXY` Region
that is used to send and receive (HTTP) session state between the client and server for you when either Spring Session is on that is used to send and receive (HTTP) session state between the client and server for you when either Spring Session
the application classpath (for example, `spring-geode-starter-session`) or you explicitly declare is on the application classpath (for example, `spring-geode-starter-session`) or you explicitly declare
the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class. the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class.
However, on the server side, you currently have a couple of options. However, on the server side, you currently have a couple of options.
First, you can manually create the cache region by using Gfsh: First, you can manually create the cache Region by using Gfsh:
.Create the Sessions Region using Gfsh .Create the Sessions Region using Gfsh
==== ====
@@ -256,13 +260,13 @@ gfsh> create region --name=MySessions --type=PARTITION --entry-idle-time-expirat
You must create the cache region with the appropriate name and an expiration policy. You must create the cache region with the appropriate name and an expiration policy.
In this case, we created an idle expiration policy with a timeout of `1800` seconds (30 minutes), after which In this case, we created an idle expiration policy with a timeout of `1800` seconds (30 minutes), after which the entry
the entry (session object) `invalidated`. (session object) is `invalidated`.
NOTE: Session expiration is managed by the Expiration Policy set on the cache region that is used to store session state. NOTE: Session expiration is managed by the Expiration Policy set on the cache Region that is used to store session state.
The servlet container's (HTTP) session expiration configuration is not used, since Spring Session replaces The Servlet container's (HTTP) session expiration configuration is not used, since Spring Session replaces the Servlet
the servlet container's session management capabilities with its own, and Spring Session delegates this behavior container's session management capabilities with its own, and Spring Session delegates this behavior to the individual
to the individual providers, such as {geode-name}. providers, such as {geode-name}.
Alternatively, you could send the definition for the cache Region from your Spring Boot `ClientCache` application Alternatively, you could send the definition for the cache Region from your Spring Boot `ClientCache` application
to the cluster by using the SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/config/annotation/EnableClusterAware.html[`@EnableClusterAware`] annotation, to the cluster by using the SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/config/annotation/EnableClusterAware.html[`@EnableClusterAware`] annotation,
@@ -274,7 +278,7 @@ which is meta-annotated with SDG's `@EnableClusterConfiguration` annotation:
---- ----
@SpringBootApplication @SpringBootApplication
@EnableClusterAware @EnableClusterAware
class MySpringBootSpringSessionApplication { class MySpringBootSpringSessionApacheGeodeApplication {
// ... // ...
} }
---- ----
@@ -284,8 +288,8 @@ TIP: See the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config
on the `@EnableClusterConfiguration` annotation and the {spring-data-geode-docs-html}/#bootstrap-annotation-config-cluster[documentation] on the `@EnableClusterConfiguration` annotation and the {spring-data-geode-docs-html}/#bootstrap-annotation-config-cluster[documentation]
for more detail. for more detail.
However, you cannot currently send expiration policy configuration metadata to the cluster. Therefore, However, you cannot currently send expiration policy configuration metadata to the cluster. Therefore, you must manually
you must manually alter the cache region to set the expiration policy: alter the cache Region to set the expiration policy:
.Using Gfsh to Alter Region .Using Gfsh to Alter Region
==== ====
@@ -296,6 +300,6 @@ gfsh> alter region --name=MySessions --entry-idle-time-expiration=1800
---- ----
==== ====
Now your Spring Boot `ClientCache` application that uses Spring Session in a client/server topology is configured to store Now your Spring Boot `ClientCache` application that uses Spring Session in a client/server topology is configured to
and manage user (HTTP) session state in the cluster. This works for either standalone, externally managed {geode-name} store and manage user (HTTP) session state in the cluster. This works for either standalone, externally managed
clusters or when you use PCC running in a {vmw-tas-name} environment. {geode-name} clusters or when you use PCC running in a {vmw-tas-name} environment.

View File

@@ -4,23 +4,23 @@
There are several ways to access data stored in {geode-name}. There are several ways to access data stored in {geode-name}.
For instance, you can use the {apache-geode-javadoc}/org/apache/geode/cache/Region.html[Region API] For instance, you can use the {apache-geode-javadoc}/org/apache/geode/cache/Region.html[Region API] directly. If you
directly. If you are driven by the application's domain context, you can use the power of are driven by the application's domain context, you can use the power of
{spring-data-commons-docs-html}/#repositories[Spring Data Repositories] instead. {spring-data-commons-docs-html}/#repositories[Spring Data Repositories] instead.
While the region API directly offers flexibility, it couples your application to {geode-name}, which is usually While the Region API offers flexibility, it couples your application to {geode-name}, which is usually undesirable
undesirable and unnecessary. While using Spring Data Repositories provides a very powerful and convenient abstraction, and unnecessary. While using Spring Data Repositories provides a very powerful and convenient abstraction, you give up
you give up the flexibility provided by a lower-level API. the flexibility provided by a lower-level Region API.
A good compromise is to use the Template pattern. Indeed, this pattern is consistently and widely used throughout A good compromise is to use the https://en.wikipedia.org/wiki/Template_method_pattern[Template software design pattern].
the entire Spring portfolio. This pattern is consistently and widely used throughout the entire Spring portfolio.
For example, the Spring Framework provides {spring-framework-javadoc}/org/springframework/jdbc/core/JdbcTemplate.html[`JdbcTemplate`] For example, the Spring Framework provides {spring-framework-javadoc}/org/springframework/jdbc/core/JdbcTemplate.html[`JdbcTemplate`]
and {spring-framework-javadoc}/org/springframework/jms/core/JmsTemplate.html[`JmsTemplate`]. and {spring-framework-javadoc}/org/springframework/jms/core/JmsTemplate.html[`JmsTemplate`].
Other Spring Data modules, such as Spring Data Redis, offer the Other Spring Data modules, such as Spring Data Redis, offer the
https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/RedisTemplate.html[`RedisTemplate`], https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/RedisTemplate.html[`RedisTemplate`],
and Spring Data for {geode-name} (SDG) offers the and Spring Data for {geode-name} (SDG) itself offers the
{spring-data-gemfire-javadoc}/org/springframework/data/gemfire/GemfireTemplate.html[`GemfireTemplate`]. {spring-data-gemfire-javadoc}/org/springframework/data/gemfire/GemfireTemplate.html[`GemfireTemplate`].
The `GemfireTemplate` provides a highly consistent and familiar API to perform data access operations on {geode-name} The `GemfireTemplate` provides a highly consistent and familiar API to perform data access operations on {geode-name}
@@ -28,39 +28,40 @@ cache `Regions`.
`GemfireTemplate` offers: `GemfireTemplate` offers:
* A simple, consistent, and convenient data access API to perform CRUD and basic query operations on cache regions. * A simple and convenient data access API to perform basic CRUD and simple query operations on cache Regions.
* Use of Spring Framework's consistent data access {spring-framework-docs}/data-access.html#dao-exceptions[exception hierarchy]. * Use of Spring Framework's consistent data access {spring-framework-docs}/data-access.html#dao-exceptions[Exception hierarchy].
* Automatic enlistment in the presence of local cache transactions. * Automatic enlistment in the presence of local cache transactions.
* Protection from {apache-geode-javadoc}/org/apache/geode/cache/Region.html[region API] breaking changes. * Consistency and protection from {apache-geode-javadoc}/org/apache/geode/cache/Region.html[Region API] breaking changes.
Given these conveniences, Spring Boot for {geode-name} (SBDG) auto-configures `GemfireTemplate` beans for each Given these advantages, Spring Boot for {geode-name} (SBDG) auto-configures `GemfireTemplate` beans for each Region
region present in the {geode-name} cache. present in the {geode-name} cache.
Additionally, SBDG is careful not to create a `GemfireTemplate` if you have already declared a `GemfireTemplate` Additionally, SBDG is careful not to create a `GemfireTemplate` if you have already declared a `GemfireTemplate` bean
bean in the Spring `ApplicationContext` for a given region. in the Spring `ApplicationContext` for a given Region.
[[geode-data-access-region-templates-explicit-declaration]] [[geode-data-access-region-templates-explicit-declaration]]
=== Explicitly Declared Regions === Explicitly Declared Regions
Consider an explicitly declared region bean definition: Consider an explicitly declared Region bean definition:
. Explicitly Declared Region Bean Definition
==== ====
[source,java] [source,java]
---- ----
@Configuration @Configuration
class GemFireConfiguration { class GeodeConfiguration {
@Bean("Example") @Bean("Example")
ClientRegionFactoryBean<?, ?> exampleRegion (GemFireCache gemfireCache) { ClientRegionFactoryBean<?, ?> exampleRegion(GemFireCache gemfireCache) {
// ... // ...
} }
} }
---- ----
==== ====
SBDG automatically creates a `GemfireTemplate` bean for the `Example` region by using a bean name `exampleTemplate`. SBDG automatically creates a `GemfireTemplate` bean for the `Example` Region by using the bean name `exampleTemplate`.
SBDG names the `GemfireTemplate` bean after the region by converting the first letter in the region's name SBDG names the `GemfireTemplate` bean after the Region by converting the first letter in the Region's name to lower case
to lower case and appending `Template` to the bean name. and appending `Template` to the bean name.
In a managed Data Access Object (DAO), you can inject the Template: In a managed Data Access Object (DAO), you can inject the Template:
@@ -70,43 +71,45 @@ In a managed Data Access Object (DAO), you can inject the Template:
@Repository @Repository
class ExampleDataAccessObject { class ExampleDataAccessObject {
@Autowired @Autowired
@Qualifier("exampleTemplate") @Qualifier("exampleTemplate")
private GemfireTemplate exampleTemplate; private GemfireTemplate exampleTemplate;
} }
---- ----
==== ====
You should use the `@Qualifier` annotation to qualify which You should use the `@Qualifier` annotation to qualify which `GemfireTemplate` bean you are specifically referring,
`GemfireTemplate` bean you are specifically referring, especially if you have more than one region, as demonstrated earlier. especially if you have more than one Region bean definition.
[[geode-data-access-region-templates-entity-defined]] [[geode-data-access-region-templates-entity-defined]]
=== Entity-defined Regions === Entity-defined Regions
SBDG auto-configures `GemfireTemplate` beans for entity-defined regions. SBDG auto-configures `GemfireTemplate` beans for entity-defined Regions.
Consider the following entity class: Consider the following entity class:
.Customer class
==== ====
[source,java] [source,java]
---- ----
@Region("Customers") @Region("Customers")
class Customer { class Customer {
// ... // ...
} }
---- ----
==== ====
Further consider the following configuration: Further consider the following configuration:
.Apache Geode Configuration
==== ====
[source,java] [source,java]
---- ----
@Configuration @Configuration
@EnableEntityDefinedRegions(basePackageClasses = Customer.class) @EnableEntityDefinedRegions(basePackageClasses = Customer.class)
class GeodeConfiguration { class GeodeConfiguration {
// ... // ...
} }
---- ----
==== ====
@@ -114,92 +117,96 @@ class GeodeConfiguration {
SBDG auto-configures a `GemfireTemplate` bean for the `Customers` Region named `customersTemplate`, which you can then SBDG auto-configures a `GemfireTemplate` bean for the `Customers` Region named `customersTemplate`, which you can then
inject into an application component: inject into an application component:
.CustomerService application component
==== ====
[source,java] [source,java]
---- ----
@Service @Service
class CustomerService { class CustomerService {
@Bean @Bean
@Qualifier("customersTemplate") @Qualifier("customersTemplate")
private GemfireTemplate customersTemplate; private GemfireTemplate customersTemplate;
} }
---- ----
==== ====
Again, be careful to qualify the `GemfireTemplate` bean injection if you have multiple regions, whether declared Again, be careful to qualify the `GemfireTemplate` bean injection if you have multiple Regions, whether declared
explicitly or implicitly, such as when you use the `@EnableEntityDefineRegions` annotation. explicitly or implicitly, such as when you use the `@EnableEntityDefineRegions` annotation.
[[geode-data-access-region-templates-caching-defined]] [[geode-data-access-region-templates-caching-defined]]
=== Caching-defined Regions === Caching-defined Regions
SBDG auto-configures `GemfireTemplate` beans for caching-defined regions. SBDG auto-configures `GemfireTemplate` beans for caching-defined Regions.
When you use Spring Framework's {spring-framework-docs}/integration.html#cache[cache abstraction] backed by When you use Spring Framework's {spring-framework-docs}/integration.html#cache[Cache Abstraction] backed by {geode-name},
{geode-name}, one requirement is to configure regions for each of the caches specified in the one requirement is to configure Regions for each of the caches specified in the
{spring-framework-docs}integration.html#cache-annotations[caching annotations] of your application service components. {spring-framework-docs}integration.html#cache-annotations[caching annotations] of your application service components.
Fortunately, SBDG makes enabling and configuring caching easy and <<geode-caching-provider,automatic>>. Fortunately, SBDG makes enabling and configuring caching easy and <<geode-caching-provider,automatic>>.
Consider the following cacheable application service component: Consider the following cacheable application service component:
.Cacheable `CustomerService` class
==== ====
[source,java] [source,java]
---- ----
@Service @Service
class CacheableCustomerService { class CacheableCustomerService {
@Bean @Bean
@Qualifier("customersByNameTemplate") @Qualifier("customersByNameTemplate")
private GemfireTemplate customersByNameTemplate; private GemfireTemplate customersByNameTemplate;
@Cacheable("CustomersByName") @Cacheable("CustomersByName")
public Customer findBy(String name) { public Customer findBy(String name) {
return toCustomer(customersByNameTemplate.query("name = " + name)); return toCustomer(customersByNameTemplate.query("name = " + name));
} }
} }
---- ----
==== ====
Further consider the following configuration: Further consider the following configuration:
.Apache Geode Configuration
==== ====
[source,java] [source,java]
---- ----
@Configuration @Configuration
@EnableCachingDefinedRegions @EnableCachingDefinedRegions
class GemFireConfiguration { class GeodeConfiguration {
@Bean @Bean
public CustomerService customerService() { public CustomerService customerService() {
return new CustomerService(); return new CustomerService();
} }
} }
---- ----
==== ====
SBDG auto-configures a `GemfireTemplate` bean named `customersByNameTemplate` to perform data access operations SBDG auto-configures a `GemfireTemplate` bean named `customersByNameTemplate` to perform data access operations on
on the `CustomersByName` (`@Cacheable`) region. You can then inject the bean into any managed application component, the `CustomersByName` (`@Cacheable`) Region. You can then inject the bean into any managed application component,
as shown in the preceding service component example. as shown in the preceding application service component example.
Again, be careful to qualify the `GemfireTemplate` bean injection if you have multiple regions, whether declared Again, be careful to qualify the `GemfireTemplate` bean injection if you have multiple Regions, whether declared
explicitly or implicitly, such as when using the `@EnableCachingDefineRegions` annotation. explicitly or implicitly, such as when you use the `@EnableCachingDefineRegions` annotation.
WARNING: Autowiring (that is, injecting) `GemfireTemplate` beans auto-configured by SBDG WARNING: Autowiring (that is, injecting) `GemfireTemplate` beans auto-configured by SBDG for caching-defined Regions
for caching-defined regions into your application components does not always work. This has to do with the Spring into your application components does not always work. This has to do with the Spring container bean creation process.
container bean creation process. In those cases, you may need to lazily lookup the `GemfireTemplate` by using In those cases, you may need to lazily lookup the `GemfireTemplate` by using
`applicationContext.getBean("customersByNameTemplate", GemfireTemplate.class)`. This is not ideal, but it works `applicationContext.getBean("customersByNameTemplate", GemfireTemplate.class)`. This is not ideal, but it works when
when autowiring does not. autowiring does not.
[[geode-data-access-region-templates-native-defined]] [[geode-data-access-region-templates-native-defined]]
=== Native-defined Regions === Native-defined Regions
SBDG even auto-configures `GemfireTemplate` beans for regions that have been defined with {geode-name} native configuration SBDG even auto-configures `GemfireTemplate` beans for Regions that have been defined with {geode-name} native
metadata, such as `cache.xml`. configuration metadata, such as `cache.xml`.
Consider the following {geode-name} native `cache.xml`: Consider the following {geode-name} native `cache.xml`:
.Client `cache.xml`
==== ====
[source,xml] [source,xml]
---- ----
@@ -217,81 +224,47 @@ Consider the following {geode-name} native `cache.xml`:
Further consider the following Spring configuration: Further consider the following Spring configuration:
.Apache Geode Configuration
==== ====
[source,java] [source,java]
---- ----
@Configuration @Configuration
@EnableGemFireProperties(cacheXmlFile = "cache.xml") @EnableGemFireProperties(cacheXmlFile = "cache.xml")
class GemFireConfiguration { class GeodeConfiguration {
// ... // ...
} }
---- ----
==== ====
SBDG auto-configures a `GemfireTemplate` bean named `exampleTemplate` after the `Example` region defined in SBDG auto-configures a `GemfireTemplate` bean named `exampleTemplate` after the `Example` Region defined in `cache.xml`.
`cache.xml`. You can inject this template as you would any other Spring-managed bean: You can inject this template as you would any other Spring-managed bean:
.Injecting the `GemfireTemplate`
==== ====
[source,java] [source,java]
---- ----
@Service @Service
class ExampleService { class ExampleService {
@Autowired @Autowired
@Qualifier("exampleTemplate") @Qualifier("exampleTemplate")
private GemfireTemplate exampleTemplate; private GemfireTemplate exampleTemplate;
} }
---- ----
==== ====
The rules described earlier apply when multiple regions are present. The rules described earlier apply when multiple Regions are present.
[[geode-data-access-region-templates-rules]] [[geode-data-access-region-templates-rules]]
=== Template Creation Rules === Template Creation Rules
Fortunately, SBDG is careful not to create a `GemfireTemplate` bean for a region if a template by the same name Fortunately, SBDG is careful not to create a `GemfireTemplate` bean for a Region if a template by the same name already
already exists. For example, consider the following configuration: exists.
==== For example, consider the following configuration:
[source,java]
----
@Configuration
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
class GemFireConfiguration {
@Bean
public GemfireTemplate customersTemplate(GemFireCache cache) {
return new GemfireTemplate(cache.getRegion("/Customers"));
}
}
----
====
Further consider the following example:
====
[source,java]
----
@Region("Customers")
class Customer {
// ...
}
----
====
Because you explicitly defined the `customersTemplate` bean, SBDG does not automatically create a template for the `Customers` region.
This applies regardless of how the region was created, whether by using `@EnableEntityDefinedRegions`,
`@EnableCachingDefinedRegions`, explicitly declaring regions, or natively defining regions.
Even if you name the template differently from the region for which the template was configured, SBDG conserves
resources and does not create the template.
For example, suppose you named the `GemfireTemplate` bean `vipCustomersTemplate`, even though the region name
is `Customers`, based on the `@Region` annotated `Customer` class, which specified the `Customers` region.
With the following configuration, SBDG is still careful not to create the Template:
.Apache Geode Configuration
==== ====
[source,java] [source,java]
---- ----
@@ -299,16 +272,58 @@ With the following configuration, SBDG is still careful not to create the Templa
@EnableEntityDefinedRegions(basePackageClasses = Customer.class) @EnableEntityDefinedRegions(basePackageClasses = Customer.class)
class GeodeConfiguration { class GeodeConfiguration {
@Bean @Bean
public GemfireTemplate vipCustomersTemplate(GemFireCache cache) { public GemfireTemplate customersTemplate(GemFireCache cache) {
return new GemfireTemplate(cache.getRegion("/Customers")); return new GemfireTemplate(cache.getRegion("/Customers"));
} }
} }
---- ----
==== ====
SBDG identifies that your `vipCustomersTemplate` is the template used with the `Customers` region, and SBDG does not Further consider the following example:
create the `customersTemplate` bean, which would result in two `GemfireTemplate` beans for the same region.
NOTE: The name of your Spring bean defined in Java configuration is the name of the method if the Spring bean is not explicitly .Customer class
named by using the `name` attribute or the `value` attribute of the `@Bean` annotation. ====
[source,java]
----
@Region("Customers")
class Customer {
// ...
}
----
====
Because you explicitly defined and declared the `customersTemplate` bean, SBDG does not automatically create a template
for the `Customers` Region. This applies regardless of how the Region was created, whether by using
`@EnableEntityDefinedRegions`, `@EnableCachingDefinedRegions`, explicitly declaring Regions,
or natively defining Regions.
Even if you name the template differently from the Region for which the template was configured, SBDG conserves
resources and does not create the template.
For example, suppose you named the `GemfireTemplate` bean `vipCustomersTemplate`, even though the Region name
is `Customers`, based on the `@Region` annotated `Customer` class, which specified the `Customers` Region.
With the following configuration, SBDG is still careful not to create the template:
.Apache Geode Configuration
====
[source,java]
----
@Configuration
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
class GeodeConfiguration {
@Bean
public GemfireTemplate vipCustomersTemplate(GemFireCache cache) {
return new GemfireTemplate(cache.getRegion("/Customers"));
}
}
----
====
SBDG identifies that your `vipCustomersTemplate` is the template used with the `Customers` Region, and SBDG does not
create the `customersTemplate` bean, which would result in two `GemfireTemplate` beans for the same Region.
NOTE: The name of your Spring bean defined in Java configuration is the name of the method if the Spring bean is not
explicitly named by using the `name` attribute or the `value` attribute of the `@Bean` annotation.

View File

@@ -4,15 +4,16 @@
:geode-name: {apache-geode-name} :geode-name: {apache-geode-name}
:stdg-website: https://github.com/spring-projects/spring-test-data-geode :stdg-website: https://github.com/spring-projects/spring-test-data-geode
Spring Boot for {geode-name} (SBDG), with help from {stdg-website}[Spring Test for {geode-name} (STDG)], offers Spring Boot for {geode-name} (SBDG), with help from {stdg-website}[Spring Test for {geode-name} (STDG)], offers
first-class support for both unit and integration testing of {geode-name} in your Spring Boot applications. first-class support for both unit and integration testing with {geode-name} in your Spring Boot applications.
TIP: See the Spring Test for Apache Geode (STDG) {stdg-website}/#stdg-in-a-nutshell[documentation] for more details. TIP: See the Spring Test for Apache Geode (STDG) {stdg-website}/#stdg-in-a-nutshell[documentation] for more details.
[[geode-testing-unit]] [[geode-testing-unit]]
=== Unit Testing === Unit Testing
Unit esting with {geode-name} using mock objects in a Spring Boot Test requires only that you declare the STDG Unit testing with {geode-name} using mock objects in a Spring Boot Test requires only that you declare the STDG
`@EnableGemFireMockObjects` annotation in your test configuration: `@EnableGemFireMockObjects` annotation in your test configuration:
.Unit Test with {geode-name} using Spring Boot .Unit Test with {geode-name} using Spring Boot
@@ -63,30 +64,30 @@ interface UserRepository extends CrudRepository<User, String> { }
==== ====
This test class is not a "`pure`" unit test, particularly since it bootstraps an actual Spring `ApplicationContext` This test class is not a "`pure`" unit test, particularly since it bootstraps an actual Spring `ApplicationContext`
using Spring Boot. It does, however, mock all {geode-name} objects, such as the `Users` `Region` declared by the using Spring Boot. However, it does mock all {geode-name} objects, such as the `Users` `Region` declared by the `User`
`User` application entity class, which was annotated with SDG's `@Region` mapping annotation. application entity class, which was annotated with SDG's `@Region` mapping annotation.
This test class conveniently uses Spring Boot's auto-configuration to auto-configure an {geode-name} `ClientCache` This test class conveniently uses Spring Boot's auto-configuration to auto-configure an {geode-name} `ClientCache`
instance. In addition, SDG's `@EnableEntityDefinedRegions` annotation was used to conveniently create the {geode-name} instance. In addition, SDG's `@EnableEntityDefinedRegions` annotation was used to conveniently create the {geode-name}
"Users` `Region` to store instances of `User`. "Users` `Region` to store instances of `User`.
Finally, Spring Data's repository abstraction was used to conveniently perform basic CRUD (such as `save`) operations and a simple Finally, Spring Data's Repository abstraction was used to conveniently perform basic CRUD (such as `save`) and simple
(OQL) query (`findById`) data access operations on the `Users` `Region`. (OQL) query (such as `findById`) data access operations on the `Users` `Region`.
Even though the {geode-name} objects (such as the `Users` `Region`) are "`mock objects`", you can still perform many of Even though the {geode-name} objects (such as the `Users` `Region`) are "`mock objects`", you can still perform many of
the data access operations required by your Spring Boot application's business logic in an {geode-name} API-agnostic way -- the data access operations required by your Spring Boot application's components in an {geode-name} API-agnostic way
that is, by using Spring's powerful programming model and constructs. -- that is, by using Spring's powerful programming model and constructs.
TIP: By extending STDG's `org.springframework.data.gemfire.tests.integration.IntegrationTestSupport` class, TIP: By extending STDG's `org.springframework.data.gemfire.tests.integration.IntegrationTestSupport` class, you ensure
you ensure that all {geode-name} mock objects and resources are properly released after the test class runs, that all {geode-name} mock objects and resources are properly released after the test class runs, thereby preventing
thereby preventing any interference with downstream tests. any interference with downstream tests.
While STDG tries to {stdg-website}/#mock-regions-with-data[mock the functionality and behavior] for many `Region` While STDG tries to {stdg-website}/#mock-regions-with-data[mock the functionality and behavior] for many `Region`
operations, it is not pragmatic to mock them all. For example, it would not be practical to mock `Region` operations, it is not pragmatic to mock them all. For example, it would not be practical to mock `Region` query
query operations involving complex OQL statements that have sophisticated predicates. operations involving complex OQL statements that have sophisticated predicates.
If such functional testing is required, the test might be better suited as an integration test. Alternatively, If such functional testing is required, the test might be better suited as an integration test. Alternatively, you can
you can follow the advice in this section about {stdg-website}/#mocking-unsupported-region-operations[unsupported region operations]. follow the advice in this section about {stdg-website}/#mocking-unsupported-region-operations[unsupported Region operations].
In general, STDG provides the following capabilities when mocking {geode-name} objects: In general, STDG provides the following capabilities when mocking {geode-name} objects:
@@ -101,8 +102,8 @@ TIP: See the documentation on {stdg-website}/#unit-testing-with-stdg[Unit Testin
=== Integration Testing === Integration Testing
Integration testing with {geode-name} in a Spring Boot Test is as simple as *not* declaring STDG's Integration testing with {geode-name} in a Spring Boot Test is as simple as *not* declaring STDG's
`@EnableGemFireMockObjects` annotation in your test configuration. You may then want to use `@EnableGemFireMockObjects` annotation in your test configuration. You may then want to use SBDG's `@EnableClusterAware`
SBDG's `@EnableClusterAware` annotation to conditionally detect the presence of a {geode-name} cluster: annotation to conditionally detect the presence of a {geode-name} cluster:
.Using `@EnableClusterAware` in test configuration .Using `@EnableClusterAware` in test configuration
==== ====
@@ -115,16 +116,16 @@ static class TestConfiguration { }
---- ----
==== ====
The SBDG `@EnableClusterAware` annotation conveniently toggles your auto-configured `ClientCache` instance The SBDG `@EnableClusterAware` annotation conveniently toggles your auto-configured `ClientCache` instance between
between local-only mode and client/server. It even pushes configuration metadata local-only mode and client/server. It even pushes configuration metadata (such as `Region` definitions) up to
(such as `Region` definitions) up to the servers in the cluster that are required by the application to persist data. the servers in the cluster that are required by the application to store data.
In most cases, in addition to testing with "`live`" {geode-name} objects (such as regions), we also want to test In most cases, in addition to testing with "`live`" {geode-name} objects (such as Regions), we also want to test in
in a client/server capacity. This unlocks the full capabilities of the {geode-name} data management system a client/server capacity. This unlocks the full capabilities of the {geode-name} data management system in a Spring
in a Spring context and gets you as close as possible to production from the comfort of your IDE. context and gets you as close as possible to production from the comfort of your IDE.
Building on our example from the section on <<geode-testing-unit>>, you can modify the test to use "`live`" Building on our example from the section on <<geode-testing-unit>>, you can modify the test to use "`live`" {geode-name}
{geode-name} objects in a client/server topology as follows: objects in a client/server topology as follows:
.Integration Test with {geode-name} using Spring Boot .Integration Test with {geode-name} using Spring Boot
==== ====
@@ -197,9 +198,10 @@ interface UserRepository extends CrudRepository<User, String> { }
The application client/server-based integration test class extend STDG's The application client/server-based integration test class extend STDG's
`org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport` class. `org.springframework.data.gemfire.tests.integration.ForkingClientServerIntegrationTestsSupport` class.
This ensures that all {geode-name} objects and resources are properly cleaned up after the test class runs. In addition, This ensures that all {geode-name} objects and resources are properly cleaned up after the test class runs. In addition,
it coordinates the client and server components of the test (for example connecting the client to the server using a random port). it coordinates the client and server components of the test (for example connecting the client to the server using a
random port).
The server is started in a `@BeforeClass` setup method: The {geode-name} server is started in a `@BeforeClass` setup method:
.Start the {geode-name} server .Start the {geode-name} server
[source,java] [source,java]
@@ -213,9 +215,9 @@ class SpringBootApacheGeodeIntegrationTest extends ForkingClientServerIntegratio
} }
---- ----
STDG lets you configure the server with Spring configuration, specified in the `TestGeodeServerConfiguration` class. STDG lets you configure the {geode-name} server with Spring configuration, specified in
The Java class needs to provide a `main` method. It uses the `SpringApplicationBuilder` to bootstrap the {geode-name} the `TestGeodeServerConfiguration` class. The Java class needs to provide a `main` method. It uses
`CacheServer` application: the `SpringApplicationBuilder` to bootstrap the {geode-name} `CacheServer` application:
.{geode-name} server configuration .{geode-name} server configuration
==== ====
@@ -241,15 +243,15 @@ In this case, we provide minimal configuration, since the configuration is deter
by the client. For example, we do not need to explicitly create the `Users` `Region` on the server since it is by the client. For example, we do not need to explicitly create the `Users` `Region` on the server since it is
implicitly handled for you by the SBDG/STDG frameworks from the client. implicitly handled for you by the SBDG/STDG frameworks from the client.
We take advantage of Spring profiles in the test setup to distinguish between the client and server configuration. Keep We take advantage of Spring profiles in the test setup to distinguish between the client and server configuration.
in mind that the test is the "`client`" in this arrangement. Keep in mind that the test is the "`client`" in this arrangement.
The STDG framework does what the supporting class demands: "`forking`" the Spring Boot-based, {geode-name} `CacheServer` The STDG framework does what the supporting class demands: "`forking`" the Spring Boot-based, {geode-name} `CacheServer`
application in a separate JVM process. Subsequently, the STDG framework stops the server upon completion of application in a separate JVM process. Subsequently, the STDG framework stops the server upon completion of the tests
the tests in the test class. in the test class.
You are free to start your servers or cluster however you choose. STDG provides You are free to start your servers or cluster however you choose. STDG provides this capability as a convenience for you,
this capability as a convenience for you, since it is a common concern. since it is a common concern.
This test class is simple. STDG can handle much more complex test scenarios. This test class is simple. STDG can handle much more complex test scenarios.