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]]
== 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
`HealthIndicators` even work with Pivotal Cloud Cache (which is backed by {pivotal-gemfire-name}) when you push your
Spring Boot applications to Pivotal CloudFoundry (PCC).
Spring Boot for {apache-geode-name} (SBDG) adds {spring-boot-docs-html}/production-ready.html[Spring Boot Actuator]
support and dedicated `HealthIndicators` for {apache-geode-name}. Equally, the provided `HealthIndicators` even work
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 applications. For instance, by querying the right `HealthIndicator` endpoint, you can
get the current hit/miss count for your `Region.get(key)` data access operations.
Spring Boot applications. For instance, by querying the right `HealthIndicator` endpoint, you can get the current
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
{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:
* Base `HealthIndicators` that apply to all {apache-geode-name}, Spring Boot applications, regardless of cache type
(such as regions, indexes, and disk stores).
* Peer `Cache`-based `HealthIndicators` that apply only to peer `Cache` applications, such as
`AsyncEventQueue`, `CacheServer`, `GatewayReceiver`, and `GatewaySender`.
* `ClientCache`-based `HealthIndicators` that apply only to `ClientCache` applications, such as
`ContinuousQuery` and connection `Pool`.
* Base `HealthIndicators` that apply to all {apache-geode-name}, Spring Boot applications, regardless of cache type,
such as `Regions`, `Indexes`, and `DiskStores`.
* Peer `Cache`-based `HealthIndicators` that apply only to peer `Cache` applications, such as `AsyncEventQueues`,
`CacheServers`, `GatewayReceivers`, and `GatewaySenders`.
* `ClientCache`-based `HealthIndicators` that apply only to `ClientCache` applications, such as `ContinuousQuery`
and connection `Pools`.
The following sections give a brief overview of all the available Spring Boot `HealthIndicators` provided for
{apache-geode-name}.
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]]
=== 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.
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).
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.
[[actuator-base-healthindicators-cache]]
==== GeodeCacheHealthIndicator
`GeodeCacheHealthIndicator` provides essential details about the (single) cache instance (client or peer) and
the underlying `DistributedSystem`, the `DistributedMember`, and configuration details of the `ResourceManager`.
`GeodeCacheHealthIndicator` provides essential details about the (single) cache instance (client or peer)
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`],
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
formed from a collection of connected peers (that is, the cluster), to which your application also has
{apache-geode-javadoc}/org/apache/geode/cache/GemFireCache.html#getDistributedSystem--[access] --
indirectly, through the cache instance.
your application as a peer member or node of the {apache-geode-javadoc}/org/apache/geode/distributed/DistributedSystem.html[`DistributedSystem`].
The distributed system (that is, the cluster) is formed from a collection of connected peers, to which your application
also has {apache-geode-javadoc}/org/apache/geode/cache/GemFireCache.html#getDistributedSystem--[access] -- indirectly,
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.
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
| 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
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,
which happens when a network partition occurs and the member gets disconnected from the cluster.
| 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.
| geode.resource-manager.critical-off-heap-percentage | Percentage of off-heap at which the cache is in danger of
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.
| 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.
|=====================================================================================================================
[[actuator-base-healthindicators-regions]]
==== GeodeRegionsHealthIndicator
`GeodeRegionsHealthIndicator` provides details about all the configured and known `Region` instances in the cache.
If the cache is a client, details include all `LOCAL`, `PROXY`, and `CACHING_PROXY` `Region` instances. If the cache
is a peer, the details include all `LOCAL`, `PARTITION`, and `REPLICATE` `Region` instances.
`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` `Regions`. If the cache is a peer
then details include all `LOCAL`, `PARTITION`, and `REPLICATE` `Region` instances.
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
| 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).
| geode.cache.regions.<name>.data-policy | Policy used to manage the data in the region
(`PARTITION`, `REPLICATE`, and others).
| geode.cache.regions.<name>.initial-capacity | Initial number of entries that can be held by a region before
it needs to be resized.
| geode.cache.regions.<name>.load-factor | Load factor used to determine when to resize the region
when it nears capacity.
| 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
(NOTE: Keys are always kept on heap).
| geode.cache.regions.<name>.pool-name | If this region is a client region, this property determines
| geode.cache.regions.<name>.data-policy | Policy used to manage data in the Region (`PARTITION`, `REPLICATE`,
and others).
| geode.cache.regions.<name>.initial-capacity | Initial number of entries that can be held by a Region before it needs
to be resized.
| geode.cache.regions.<name>.load-factor | Load factor used to determine when to resize the Region when it nears
capacity.
| 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
(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
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
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>.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.
| 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
[width="90%",cols="^3,<10",options="header"]
|=====================================================================================================================
| Name | Description
| geode.cache.regions.<name>.partition.collocated-with | Indicates whether this region is collocated with another
`PARTITION` egion, which is necessary when performing equi-joins queries (NOTE: distributed joins are not supported).
| geode.cache.regions.<name>.partition.collocated-with | Indicates whether this Region is collocated with
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
this region on this node.
| geode.cache.regions.<name>.partition.redundant-copies | Number of replicas for this `PARTITION` region,
this Region on this node.
| geode.cache.regions.<name>.partition.redundant-copies | Number of replicas for this `PARTITION` Region,
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
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
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
is divided (defaults to 113).
|=====================================================================================================================
Finally, when statistics are enabled (for example, when you use `@EnableStatistics` --
(see {spring-data-geode-docs-html}/#bootstrap-annotation-config-statistics[here]
for more details), the following details are available:
(see {spring-data-geode-docs-html}/#bootstrap-annotation-config-statistics[doc] for more details),
the following metadata is available:
.Region Statistic Details
[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.last-accessed-time | For an entry, indicates the last time it was accessed
with `Region.get(key)`.
| geode.cache.regions.<name>.statistics.last-modified-time | For an entry, indicates the time when a region's entry value
was last modified.
| geode.cache.regions.<name>.statistics.last-modified-time | For an entry, indicates the time when a Region's entry
value was last modified.
| geode.cache.regions.<name>.statistics.miss-count | Returns the number of times that a `Region.get`
was performed and no value was found locally.
|=====================================================================================================================
[[actuator-base-healthindicators-indexes]]
==== GeodeIndexesHealthIndicator
`GeodeIndexesHealthIndicator` provides details about the configured region `Index` instances used in OQL query
data access operations.
`GeodeIndexesHealthIndicator` provides details about the configured Region `Indexes` used by OQL query data access
operations.
The following details are covered:
@@ -204,31 +205,30 @@ The following details are covered:
| Name | Description
| 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>.projection-attributes | For map indexes, returns either `*`
or the specific map keys that were indexed. For all other indexes, returns `*`.
| geode.index.<name>.region | Region to which the index is applied.
| 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 `*` or the specific Map keys
that were indexed. For all other `Indexes`, returns `*`.
| geode.index.<name>.region | Region to which the Index is applied.
|=====================================================================================================================
Additionally, when statistics are enabled (for example, when you use `@EnableStatistics` --
see {spring-data-geode-docs-html}/#bootstrap-annotation-config-statistics["`Configuring Statistics`"]
for more details), the following details are available:
see {spring-data-geode-docs-html}/#bootstrap-annotation-config-statistics["`Configuring Statistics`"] for more details),
the following metadata is available:
.Index Statistic Details
[width="90%",cols="^3,<10",options="header"]
|=====================================================================================================================
| 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-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-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.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
this index.
| geode.index.<name>.statistics.total-uses | Total number of times this index has been accessed by
| 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-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-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.total-update-time | Total amount of time (ns) spent updating this Index.
| geode.index.<name>.statistics.total-uses | Total number of times this Index has been accessed by
an OQL query.
|=====================================================================================================================
@@ -237,8 +237,8 @@ an OQL query.
==== GeodeDiskStoresHealthIndicator
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
when the values in the regions have been serialized with PDX and the regions are persistent.
Remember, `DiskStores` are used to overflow and persist data to disk, including type metadata tracked by PDX when the
values in the Regions have been serialized with PDX and the Regions are persistent.
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
the total disk volume.
| 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
from the queue if the size limit has not be reached.
| geode.disk-store.<name>.uuid | Universally unique identifier for the DiskStore across
a distributed system.
| geode.disk-store.<name>.uuid | Universally unique identifier for the DiskStore across a
distributed system.
| geode.disk-store.<name>.write-buffer-size | Size the of write buffer the DiskStore uses to write data
to disk.
@@ -279,23 +280,23 @@ instance (that is, the application is a cache client), which is the default.
[[actuator-clientcache-healthindicators-cq]]
==== GeodeContinuousQueriesHealthIndicator
`GeodeContinuousQueriesHealthIndicator` provides details about registered client continuous queries (CQs).
CQs let client applications receive automatic notification about events that satisfy some criteria. That criteria
can be easily 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,
an event is sent to the registered client.
`GeodeContinuousQueriesHealthIndicator` provides details about registered client Continuous Queries (CQs). CQs let
client applications receive automatic notification about events that satisfy some criteria. That criteria can be easily
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
("data of interests"), an event is sent to the registered client.
The following details are covered for CQs by name:
.Continuous Query(CQ) Details
.Continuous Query (CQ) Details
[width="90%",cols="^3,<10",options="header"]
|=====================================================================================================================
| Name | Description
| 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>.closing | Indicates whether the CQ is the process of closing.
| geode.continuous-query.<name>.durable | Indicates whether the CQ events is remembered
| 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 are remembered
between client sessions.
| geode.continuous-query.<name>.running | Indicates whether the CQ is currently running.
| 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:
.Continuous Query(CQ), Query Details
.Continuous Query (CQ), Query Details
[width="90%",cols="^3,<10",options="header"]
|=====================================================================================================================
| Name | Description
| 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>.statistics.number-of-deletes |
|=====================================================================================================================
.Continuous Query(CQ), Statistic Details
[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
additional details on the client:
The {apache-geode-name} Continuous Query system is also tracked with the following additional details on the client:
.Continuous Query(CQ), Statistic Details
.Continuous Query (CQ), Additional Statistic Details
[width="90%",cols="^3,<10",options="header"]
|=====================================================================================================================
| Name | Description
@@ -349,8 +347,8 @@ additional details on the client:
[[actuator-clientcache-healthindicators-pools]]
==== GeodePoolsHealthIndicator
`GeodePoolsHealthIndicator` provides details about all the configured client connection `Pools`.
This `HealthIndicator` primarily provides configuration metadata for all the configured `Pools`.
`GeodePoolsHealthIndicator` provides details about all the configured client connection `Pools`. This `HealthIndicator`
primarily provides configuration metadata for all the configured `Pools`.
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.<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
from the pool.
| geode.pool.<name>.idle-timeout | The amount of time to wait before closing unused
idle connections, not exceeding the configured number of minimum required connections.
| geode.pool.<name>.load-conditioning-interval | 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.
| geode.pool.<name>.locators | List of configured locators.
| 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>.multi-user-authentication | Determines whether the pool can be used by
multiple authenticated users.
| geode.pool.<name>.online-locators | Returns a list of living locators.
| geode.pool.<name>.pending-event-count | Approximate number of pending subscription events
maintained at server for this durable client pool at the time it (re)connected to the server.
from the Pool.
| geode.pool.<name>.idle-timeout | The amount of time to wait before closing unused, idle
connections, not exceeding the configured number of minimum required connections.
| geode.pool.<name>.load-conditioning-interval | How frequently the Pool checks to see whether a connection
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>.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>.multi-user-authentication | Determines whether the Pool can be used by multiple
authenticated users.
| geode.pool.<name>.online-locators | Returns a list of living Locators.
| geode.pool.<name>.pending-event-count | Approximate number of pending subscription events maintained
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>.pr-single-hop-enabled | Whether the client acquires a direct connection to
the 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).
| geode.pool.<name>.retry-attempts | Number of times to retry a request after a timeout or an exception.
| geode.pool.<name>.server-group | All the servers must belong to the same group, and this
value sets the name of that group.
| geode.pool.<name>.retry-attempts | Number of times to retry a request after a timeout
or an exception.
| 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>.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>.subscription-ack-interval | Interval in milliseconds to wait before sending
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-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.
| 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.
| 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]]
=== 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.
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
class.
`@PeerCacheApplication` or, alternatively, the `@CacheServerApplication` annotation on your
`@SpringBootApplication`-annotated class.
[[actuator-peercache-healthindicators-cacheservers]]
==== GeodeCacheServersHealthIndicator
@@ -433,8 +431,7 @@ is bound (useful when the system contains multiple NICs).
(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>.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
a client queue.
| geode.cache.server.<index>.max-message-count | Maximum number of messages that can be put in a client queue.
| geode.cache.server.<index>.max-threads | Maximum number of threads allowed in this `CacheServer`
to service client requests.
| 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.
| geode.cache.server.<index>.running | Determines whether this `CacheServer` is currently running
and accepting client connections.
| geode.cache.server.<index>.socket-buffer-size | Configured buffer size of the socket connection
used by this CacheServer.
| geode.cache.server.<index>.socket-buffer-size | Configured buffer size of the socket connection used by
this CacheServer.
| 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
about the runtime characteristics of the `CacheServer`:
In addition to the configuration settings shown in the preceding table, the `ServerLoadProbe` of the `CacheServer`
tracks additional details about the runtime characteristics of the `CacheServer`:
.CacheServer Metrics and Load Details
[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
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.load-per-subscription-connection | Estimate of the how much load each new subscriber
adds to this server.
| geode.cache.server.<index>.load.load-per-subscription-connection | Estimate of how much load each new subscriber adds
to this server.
| 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
`CacheServer`.
@@ -476,10 +473,10 @@ adds to this server.
[[actuator-peercache-healthindicators-aeq]]
==== GeodeAsyncEventQueuesHealthIndicator
`GeodeAsyncEventQueuesHealthIndicator` provides details about the configured `AsyncEventQueue` instances. AEQs can be
attached to regions to configure asynchronous write-behind behavior.
`GeodeAsyncEventQueuesHealthIndicator` provides details about the configured `AsyncEventQueues`. AEQs can be attached to
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
[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
to disk.
| 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)
or serial.
| 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]]
==== GeodeGatewayReceiversHealthIndicator
`GeodeGatewayReceiversHealthIndicator` provide details about the configured (WAN) `GatewayReceivers`, which are
capable of receiving events from remote clusters when using {apache-geode-name}'s
`GeodeGatewayReceiversHealthIndicator` provides details about the configured (WAN) `GatewayReceivers`,
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].
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
[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.<index>.bind-address | IP address of the NIC to which the `GatewayReceiver`
`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`
is chosen.
| geode.gateway-receiver.<index>.host | IP address or hostname that locators tell clients
(that is, `GatewaySender` instances) on which this `GatewayReceiver` listens.
| geode.gateway-receiver.<index>.end-port | End value of the port range from which the port of
the `GatewayReceiver` is chosen.
| geode.gateway-receiver.<index>.host | IP address or hostname that Locators tell clients (that is,
`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>.port | Port on which this `GatewayReceiver` listens for clients
(that is, `GatewaySender` instances).
@@ -536,17 +532,17 @@ is chosen.
and accepting client connections (from `GatewaySender` instances).
| geode.gateway-receiver.<index>.socket-buffer-size | Configured buffer size for the socket connections used by
this `GatewayReceiver`.
| geode.gateway-receiver.<index>.start-port | Start value of the port range from which the
port of the `GatewayReceiver` port is chosen.
| geode.gateway-receiver.<index>.start-port | Start value of the port range from which the port of
the `GatewayReceiver` is chosen.
|=====================================================================================================================
[[actuator-peercache-healthindicators-gateway-senders]]
==== GeodeGatewaySendersHealthIndicator
The `GeodeGatewaySendersHealthIndicator` provides details about the configured `GatewaySender` instances. `GatewaySender` 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].
The `GeodeGatewaySendersHealthIndicator` provides details about the configured `GatewaySenders`. `GatewaySender`
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].
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
is sent.
| geode.gateway-sender.<id>.disk-store-name | Name of the `DiskStore` used to overflow and persist
queue events.
| geode.gateway-sender.<id>.disk-synchronous | Indicates whether disk writes are synchronous or asynchronous.
queued events.
| 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>.max-parallelism-for-replicated-region |
| geode.gateway-sender.<id>.max-queue-memory | Maximum amount of memory (MB) usable for this
`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
to `GatewayReceiver` instances.
| geode.gateway-sender.<id>.parallel | Indicates whether this `GatewaySender` is parallel
(higher throughput) or serial.
| geode.gateway-sender.<id>.paused | Indicates whether this `GatewaySender` is paused.
| geode.gateway-sender.<id>.persistent | Indicates whether this `GatewaySender` persists queue
events to disk.
| geode.gateway-sender.<id>.persistent | Indicates whether this `GatewaySender` persists
queue events to disk.
| geode.gateway-sender.<id>.remote-distributed-system-id | Identifier for the remote distributed system.
| geode.gateway-sender.<id>.running | Indicates whether this `GatewaySender`
is currently running.
| geode.gateway-sender.<id>.socket-buffer-size | Configured buffer size for the socket connections
between this `GatewaySender` and its receiving `GatewayReceiver`.
| geode.gateway-sender.<id>.socket-read-timeout | Amount of time (ms) that a socket read between
this sending `GatewaySender` and its receiving `GatewayReceiver` blocks.
between this `GatewaySender` and the receiving `GatewayReceiver`.
| geode.gateway-sender.<id>.socket-read-timeout | Amount of time (ms) that a socket read between this
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
in the `exclude` attribute using array syntax:
You can disable more than one auto-configuration class at a time by specifying each class in the `exclude` attribute
using array syntax:
.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`
[[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
`spring-gemfire-starter` and 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
based on {geode-name} 1.12, and SBDG can no longer properly support standalone GemFire bits (version <= 9.10).
`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 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
was Pivotal Cloud Cache (PCC) running on Pivotal CloudFoundry (PCF) has been rebranded as
{pivotal-cloudcache-website}[VMware Tanzu GemFire for VMs]
and {pivotal-cloudfoundry-website}[VMware Tanzu Application Service (TAS)], respectively.
NOTE: What was Pivotal GemFire has now been rebranded as {pivotal-gemfire-website}[{pivotal-gemfire-name}]
and what was Pivotal Cloud Cache (PCC) running on Pivotal CloudFoundry (PCF) has been rebranded as
{pivotal-cloudcache-website}[{pivotal-cloudcache-name}] and {pivotal-cloudfoundry-website}[{pivotal-cloudfoundry-name} (TAS)],
respectively.
[[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
from inside your IDE using Spring Boot. This is extremely helpful during development, since it you manually
spin up, test, and debug your applications quickly and easily.
As described in <<geode-clientcache-applications>>, you can configure and run a small {geode-name} cluster from inside
your IDE using Spring Boot. This is extremely helpful during development because it enables you to manually run, test,
and debug your applications quickly and easily.
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
and join them together to form a small cluster by modifying the runtime configuration of this class ever so
slightly.
and join them together to form a small cluster. You only need to modify the runtime configuration of this class
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
join the cluster as a peer. The locator service also lets clients connect to the servers
in the cluster. When the cache client's pool is configured to use locators, the pool can intelligently
route data requests directly to the server hosting the data (a.k.a. single-hop access), especially when the data
is partitioned/sharded across servers in the cluster. Locator pools include support for load balancing connections
and handling automatic fail-over in the event of failed connections, among other things.
The Locator enables members in the cluster to locate one another and lets new members join the cluster as a peer.
The Locator also lets clients connect to the servers in the cluster. When the cache client's connection pool
is configured to use Locators, the pool of connections can intelligently route data requests directly to the server
hosting the data (a.k.a. single-hop access), especially when the data is partitioned/sharded across multiple servers
in the cluster. Locator-based connection pools include support for load balancing connections and handling automatic
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]).
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
====
@@ -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
====
@@ -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
that the members in a cluster be named, and the names of each member in the cluster be unique.
To do so, you must vary the name of the members you add to your cluster as peers. {geode-name} requires members in a
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,
which also embeds a `CacheServer` instance enabling cache clients to connect, we need to be careful to vary our
ports used by the embedded services.
which also embeds a `CacheServer` component enabling cache clients to connect. Therefore, you must vary the ports
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).
Therefore, we can switch profiles from non-clustered to using the Spring `clustered` profile, which includes different
Fortunately, you do not need to run another embedded Locator or Manager (you need only one of each in this case).
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,
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
run profile configuration:
To add another server, set the member name and `CacheServer` port to different values with the following
run configuration:
.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
in the nested `ClusteredConfiguration` class while disabling the `LonerConfiguration` class.
Notice that we explicitly activated the "clustered" Spring profile, which enables the configuration provided in
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`
property to `localhost[10334]`. By default, it assumes that the locator process/service runs on locahost,
listening on the default locator port of 10334. You can adjust your locators endpoint if your locators
run elsewhere in your network by using the `locators` attribute of the `@UseLocators` annotation.
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 runs on localhost, listening on the default
Locator port of 10334. You can adjust your `locators` connection endpoint if your Locators run elsewhere in your network
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
provides redundancy in case a Locator process fails. If all locator processes in your network fail,
your cluster does not go down. It means that no other members can join the cluster, letting you
scale out your cluster. Any clients also cannot connect. Restart the Locators if this happens.
TIP: In production environments, it is common to run multiple Locators in separate processes. Running multiple Locators
provides redundancy in case a Locator fails. If all Locators in your cluster fail, then your cluster will continue to
run, but no other members will be able to join the cluster, which is important when scaling out the cluster. Clients
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
when it joins the cluster as a peer.
Also, we set the `spring.data.gemfire.name` property to `ServerTwo`, adjusting the name of our member when it joins
the cluster as a peer.
Finally, we set the `spring.data.gemfire.cache.server.port` to `41414` to vary the `CacheServer` port
used by `ServerTwo`. The default `CacheServer` port is `40404`. If we had not set this property before starting
`ServerTwo`, we would have hit a `java.net.BindException`.
Finally, we set the `spring.data.gemfire.cache.server.port` property to `41414` to vary the `CacheServer` port used by
`ServerTwo`. The default `CacheServer` port is `40404`. If we had not set this property before starting `ServerTwo`,
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
used by SDG to dynamically configure {geode-name} with a Spring Boot `application.properties` file
or Java System properties. You can find these properties in the annotation Javadoc in SDG's annotation-based
configuration model. For example, see the Javadoc for the
TIP: Both `spring.data.gemfire.name` and `spring.data.gemfire.cache.server.port` are well-known properties used by SDG
to dynamically configure {geode-name} with a Spring Boot `application.properties` file or by using Java System
properties. You can find these properties in the annotation Javadoc in SDG's annotation-based configuration model.
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].
Most of the SDG annotations include corresponding properties that can be defined in `application.properties`
and is explained in more detail {spring-data-geode-docs-html}/#bootstrap-annotation-config-properties[documentation].
Most SDG annotations include corresponding properties that can be defined in Spring Boot `application.properties`,
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
when we again `list members` and `describe member`:
After starting our second server, `ServerTwo`, we should see output similar to the following at the command-line
and in Gfsh when we again `list members` and `describe member`:
.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
is appropriately set to `41414`.
When we list the members of the cluster, we see `ServerTwo`, and when we `describe` `ServerTwo`, we see that its
`CacheServer` port is appropriately set to `41414`.
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.
To do so, include and use Spring Boot for {geode-name}.
Now you can build and run a Spring Boot, {geode-name} `ClientCache` application that connects to this cluster. To do so,
include and use Spring Boot for {geode-name}.
[[geode-testing-support]]
=== Testing
https://github.com/spring-projects/spring-test-data-geode[Spring Test for {geode-name}] is a new, soon-to-be-released
and upcoming project to help you write both unit and integration tests when you use {geode-name} in a Spring
context.
In fact, the entire {github-url}/tree/master/spring-geode-autoconfigure/src/test/java/org/springframework/geode/boot/autoconfigure[test suite]
https://github.com/spring-projects/spring-test-data-geode[Spring Test for {geode-name}] (STDG) is a relatively new project
to help you write both unit and integration tests when you use {geode-name} in a Spring context. 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.
All Spring projects that integrate with {geode-name} will use this new test framework for all their testing needs, making
this new test framework for {geode-name} a proven and reliable solution for all your {geode-name} application testing
needs when using Spring as well.
All Spring projects that integrate with {geode-name} will use this new test framework for all their testing needs,
making this new test framework for {geode-name} a proven and reliable solution for all your {geode-name} application
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]]
=== 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 <<geode-samples,samples>>.
See also the https://github.com/jxblum/temperature-service[Temperature Service], Spring Boot
application that implements a temperature sensor and monitoring, internet of things (IOT) example. The example uses SBDG
to showcase {geode-name} CQ, function implementations and executions, and positions {geode-name} as a caching provider
in Spring's cache abstraction. It is a working, sophisticated, and complete example, and we highly recommend it as a good
starting point for real-world use cases.
See also the https://github.com/jxblum/temperature-service[Temperature Service], Spring Boot application that implements
a temperature sensor and monitoring, Internet of Things (IOT) example. The example uses SBDG to showcase {geode-name} CQ,
function implementations and executions, and positions {geode-name} as a caching provider in Spring's Cache Abstraction.
It is a working, sophisticated, and complete example, and we highly recommend it as a good starting point for real-world
use cases.
See the https://github.com/jxblum/contacts-application/tree/master/boot-example[Boot example]
from the contact application reference implementation (RI) for Spring Data for {geode-name} (SDG) as yet another
example.
See the https://github.com/jxblum/contacts-application/tree/master/boot-example[Boot example] from the contact
application reference implementation (RI) for Spring Data for {geode-name} (SDG) as yet another example.
[[references]]
=== References

View File

@@ -3,25 +3,26 @@
:gemfire-name: {pivotal-gemfire-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
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]
{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
{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]
behind Spring's cache abstraction before you continue.
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
simple {spring-boot-docs-html}/#_supported_cache_providers[caching providers].
in Spring Boot's reference documentation. Spring Boot even provides auto-configuration support for a few of the simple
{spring-boot-docs-html}/#_supported_cache_providers[caching providers].
Indeed, caching can be an effective software design pattern to avoid the cost of invoking
a potentially expensive operation when, given the same input, the operation yields the same output every time.
Indeed, caching can be an effective software design pattern to avoid the cost of invoking a potentially expensive
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,
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}.
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
the appropriate Spring cache annotations.
simple to get started with caching, which is as easy as annotating your application components with the appropriate
Spring cache annotations.
TIP: Spring's declarative, annotation-based caching also {spring-framework-docs}/integration.html#cache-jsr-107[supports]
JCache (JSR-107) annotations.
For example, suppose you want to cache the results of determining a person's eligibility when applying for a
loan. A person's financial status is unlikely to change in the time that the computer runs the algorithms to compute
a person's eligibility after all the financial information for the person has been collected and submitted for review
and processing.
For example, suppose you want to cache the results of determining a person's eligibility when applying for a loan. A
person's financial status is unlikely to change in the time that the computer runs the algorithms to compute a person's
eligibility after all the financial information for the person has been collected, submitted for review and processed.
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.
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,
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.
@@ -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
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}
does not function as the caching provider for the application. This lets you configure another store, such as
If Spring Boot for {geode-name} detects that another cache provider has already been configured, then {geode-name}
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.
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
on which caching has been applied is invoked. This means the backend data store must provide the data structure
that serves as the cache. For {geode-name}, this means a cache `Region`.
on which caching was applied is invoked. This means the backend data store must provide the data structure that serves
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,
use Spring Data for {geode-name}'s
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegions.html[`@EnableCachingDefinedRegions`]
To configure the necessary Regions that back the caches declared in Spring's cache annotations, use Spring Data
for {geode-name}'s {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableCachingDefinedRegions.html[`@EnableCachingDefinedRegions`]
annotation.
The following listing shows a complete Spring Boot application:
.Spring Boot cache enabled application using {geode-name}
====
[source,java]
----
@@ -106,8 +106,8 @@ class FinancialLoanApplication {
TIP: The `FinancialLoanApplicationService` is picked up by Spring's classpath component scan, since this class
is annotated with Spring's `@Service` stereotype annotation.
TIP: You can set the `DataPolicy` of the region created through the `@EnableCachingDefinedRegions` annotation by
setting the `clientRegionShortcut` to a valid enumerated value.
TIP: You can set the `DataPolicy` of the Region created through the `@EnableCachingDefinedRegions` annotation
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
should use SDG's `@EnableCachingDefinedRegions` on an appropriate Spring Boot application `@Configuration` class.
@@ -120,43 +120,44 @@ needs:
* Look-aside caching
* Near caching
* Inline caching
* [Async] Inline caching
* Multi-site 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.
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.
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
amount of work completed in a given period of time.
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 amount of work completed in a given period of time.
Within inline caching_, developers have a choice between synchronous (read/write-through) and asynchronous
(write-behind_) configurations depending on the application use case and requirements. Synchronous, read/write-through
inline caching is necessary if consistency is a concern. Asynchronous, write-behind inline caching is applicable
if throughput and low-latency are a priority.
Within Inline caching_, developers have a choice between synchronous (read/write-through) and asynchronous (write-behind)
configurations depending on the application use case and requirements. Synchronous, read/write-through Inline caching
is necessary if consistency is a concern. Asynchronous, write-behind Inline caching is applicable if throughput
and low-latency are a priority.
Within multi-site caching, there are active-passive and active-active arrangements. More details on multi-site
caching will be presented in a later release.
Within Multi-site caching, there are active-active and active-passive arrangements. More details on Multi-site caching
will be presented in a later release.
[[geode-caching-provider-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]
to see look-aside caching with {apache-geode-name} in action.
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.
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
operation, such as an operation that makes an IO- or network-bound request that results in either a blocking
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
invoking the expensive operation. If the data cannot be found in the cache, the operation must be invoked.
However, before returning, the result of the operation is cached for subsequent requests when the the same input
is requested again by another caller, resulting in much improved response times.
If the data can be found in the cache (stored in-memory to reduce latency), the data is returned without ever invoking
the expensive operation. If the data cannot be found in the cache, the operation must be invoked. However, before
returning, the result of the operation is cached for subsequent requests when the same input is requested again by
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
====
@@ -183,37 +184,36 @@ class CustomerService {
====
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 `findByAccount(:Account):Customer` operation to provide caching facilities.
the external data source (for example, an RDBMS) directly. The `@Cacheable` annotation wraps, or "decorates",
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.
[[geode-caching-provider-near-caching]]
==== Near Caching
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
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>>
an auto-configured `ClientCache` instance by default. A `ClientCache` instance is most effective
when the data access operations, including cache access, are distributed to the servers in a cluster that is accessible to the
client and, in most cases, multiple clients. This lets other cache client applications access the same data.
However, this also means the application incurs a network hop penalty to evaluate the presence of the data
in the cache.
an auto-configured `ClientCache` instance by default. A `ClientCache` instance is most effective when the data access
operations, including cache access, are distributed to the servers in a cluster that is accessible to the client and,
in most cases, multiple clients. This lets other cache client applications access the same data. However, this also
means the application incurs a network hop penalty to evaluate the presence of the data in the cache.
To help avoid the cost of this network hop in a client/server topology, a local cache can be established to
maintain a subset of the data in the corresponding server-side cache (that is, a region). Therefore, the client cache
contains only the data of interest to the application. This "`local`" cache (that is, a client-side region) is consulted
before forwarding the lookup request to the server.
To help avoid the cost of this network hop in a client/server topology, a local cache can be established to maintain
a subset of the data in the corresponding server-side cache (that is, a Region). Therefore, the client cache contains
only the data of interest to the application. This "local" cache (that is, a client-side Region) is consulted before
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
cache abstraction) data management policy from `PROXY` (the default) to `CACHING_PROXY`:
To enable Near caching when using {geode-name}, change the Region's (that is the `Cache` in Spring's Cache Abstraction)
data management policy from `PROXY` (the default) to `CACHING_PROXY`:
.Enabling Near Caching using {geode-name}
.Enable Near Caching with {geode-name}
====
[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`].
As a result, all data access operations are immediately forwarded to the server.
TIP: See also the {geode-name} documentation concerning
{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
in addition to the corresponding server-side region. This is necessary to receive updates on entries in the region
that might have been changed by other clients that have access to the same data.
and, specifically, "`Client Interest Registration on the Server,`" which applies when you use client `CACHING_PROXY`
Regions to manage state in addition to the corresponding server-side Region. This is necessary to receive updates on
entries in the Region that might have been changed by other clients that have access to the same data.
[[geode-caching-provider-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
when you use the inline caching pattern: synchronous (read/write-through) and asynchronous (write-behind).
You can apply two different configurations of Inline caching to your Spring Boot applications when you use
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.
There is no option to asynchronously and automatically load the cache when the value becomes available in the
external data source.
NOTE: Asynchronous (currently) offers only write capabilities, from the cache to the external data source. There is no
option to asynchronously and automatically load the cache when the value becomes available in the external data source.
[[geode-caching-provider-inline-caching-synchronous]]
===== Synchronous Inline Caching
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.
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
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
data store, such as Apache Cassandra, MongoDB, or Neo4j).
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 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 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.
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
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`"
operation, because it is synchronous. If the backend data store fails to be updated, the entry is not stored in
the region. This helps to ensure consistency between the backend data store and the {geode-name} region.
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 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 operation, because it is synchronous. If the backend data store fails to be updated, the entry is
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
an {apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventListener.html[`AsyncEventListener`] on an
{apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventQueue.html[`AsyncEventQueue`] attached to a server-side region.
See the {geode-name} User Guide for more
{apache-geode-docs}/developing/events/implementing_write_behind_event_handler.html[detail]. We cover asynchronous
write-behind inline caching in the next section.
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 {apache-geode-javadoc}/org/apache/geode/cache/asyncqueue/AsyncEventQueue.html[`AsyncEventQueue`] attached to
a server-side Region. See {geode-name}'s User Guide for more
{apache-geode-docs}/developing/events/implementing_write_behind_event_handler.html[details]. We cover asynchronous
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
====
@@ -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
and the `CustomerRepository` accesses {geode-name} directly and NOT the RDBMS.
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 the RDBMS indirectly.
[[geode-caching-provider-inline-caching-synchronous-cacheloader-cachewriter]]
====== Implementing CacheLoaders and CacheWriters for Inline Caching
You can use Spring to configure a `CacheLoader` or `CacheWriter` as a bean in the Spring `ApplicationContext`
and then wire the loader or writer to a region. Given that the `CacheLoader` or `CacheWriter` is a Spring bean
like any other bean in the Spring `ApplicationContext`, you can inject any `DataSource` you like into the loader or writer.
You can use Spring to configure a `CacheLoader` or `CacheWriter` as a bean in the Spring `ApplicationContext` and then
wire the loader or writer to a Region. Given that the `CacheLoader` or `CacheWriter` is a Spring bean like any other
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
configure the corresponding server-side region:
While you can configure client Regions with `CacheLoaders` and `CacheWriters`, it is more common to configure
the corresponding server-side Region:
====
[source,java]
@@ -331,33 +331,32 @@ class FinancialLoanApplicationServer {
@Bean("EligibilityDecisions")
PartitionedRegionFactoryBean<Object, Object> eligibilityDecisionsRegion(
GemFireCache gemfireCache, CacheLoader decisionManagementSystemLoader,
CacheWriter decisionManagementSystemWriter) {
GemFireCache gemfireCache, CacheLoader eligibilityDecisionLoader,
CacheWriter eligibilityDecisionWriter) {
PartitionedRegionFactoryBean<?, EligibilityDecision> eligibilityDecisionsRegion =
new PartitionedRegionFactoryBean<>();
eligibilityDecisionsRegion.setCache(gemfireCache);
eligibilityDecisionsRegion.setCacheLoader(decisionManagementSystemLoader);
eligibilityDecisionsRegion.setCacheWriter(decisionManagementSystemWriter);
eligibilityDecisionsRegion.setCacheLoader(eligibilityDecisionLoader);
eligibilityDecisionsRegion.setCacheWriter(eligibilityDecisionWriter);
eligibilityDecisionsRegion.setPersistent(false);
return eligibilityDecisionsRegion;
}
@Bean
CacheLoader<?, EligibilityDecision> decisionManagementSystemLoader(
CacheLoader<?, EligibilityDecision> eligibilityDecisionLoader(
DataSource dataSource) {
return new DecisionManagementSystemLoader(dataSource);
return new EligibilityDecisionLoader(dataSource);
}
@Bean
CacheWriter<?, EligibilityDecision> decisionManagementSystemWriter(
CacheWriter<?, EligibilityDecision> eligibilityDecisionWriter(
DataSource dataSource) {
return new DecisionManagementSystemWriter(dataSource);
return new EligibilityDecisionWriter(dataSource);
}
@Bean
@@ -371,24 +370,25 @@ class FinancialLoanApplicationServer {
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:
.DecisionManagementSystemLoader
.EligibilityDecisionLoader
====
[source,java]
----
class DecisionManagementSystemLoader implements CacheLoader<?, EligibilityDecision> {
class EligibilityDecisionLoader implements CacheLoader<?, EligibilityDecision> {
private final DataSource dataSource;
DecisionManagementSystemLoader(DataSource dataSource) {
EligibilityDecisionLoader(DataSource dataSource) {
this.dataSource = dataSource;
}
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
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:
.DecisionManagementSystemWriter
.EligibilityDecisionWriter
====
[source,java]
----
class DecisionManagementSystemWriter implements CacheWriter<?, EligibilityDecision> {
class EligibilityDecisionWriter implements CacheWriter<?, EligibilityDecision> {
private final DataSource dataSource;
DecisionManagementSystemWriter(DataSource dataSource) {
EligibilityDecisionWriter(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
conveniently implement application `CacheWriters`.
TIP: SBDG provides the `org.springframework.geode.cache.support.CacheWriterSupport` interface to conveniently implement
application `CacheWriters`.
NOTE: Your `CacheWriter` implementation can use any data access technology to interface with
your backend data store (for example JDBC, Spring's `JdbcTemplate`, JPA with Hibernate, and others). It is not limited to using only
a `javax.sql.DataSource`. In fact, we present another, more useful and convenient approach to implementing
inline caching in the next section.
NOTE: Your `CacheWriter` implementation can use any data access technology to interface with your backend data store
(for example JDBC, Spring's `JdbcTemplate`, JPA with Hibernate, and others). It is not limited to using only a
`javax.sql.DataSource`. In fact, we present another, more useful and convenient approach to implementing Inline caching
in the next section.
[[geode-caching-provider-inline-caching-synchronous-using-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
Repositories.
Spring Boot for {geode-name} offers dedicated support to configure Inline caching with Spring Data Repositories.
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,
MongoDB for documents, Neo4j for graphs, Elasticsearch for search, and so on).
* Access any backend data store supported by Spring Data (such as Redis for key-value or other distributed data
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).
We believe that users should store data where it is most easily accessible. If you access
and process documents, then MongoDB, Couchbase, or another document store is probably going to be the most logical
choice to manage your application's documents.
We believe that users should store data where it is most easily accessible. If you access and process documents,
then MongoDB, Couchbase, or another document store is probably going to be the most logical choice to manage
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
each data store for what it is good at. While MongoDB is excellent at handling documents, {geode-name} is a highly
valuable choice for consistency, high availability, low-latency, high-throughput, multi-site, scale-out application
use cases.
each data store for what it is good at. While MongoDB is excellent at handling documents, {geode-name} is a valuable
choice for consistency, high-availability/low-latency, high-throughput, multi-site, scale-out application use cases.
As such, using {geode-name}'s `CacheLoader` and `CacheWriter` provides a nice integration point between itself
and other data stores to best serve your application's use case and requirements.
As such, using {geode-name}'s `CacheLoader` and `CacheWriter` provides a nice integration point between itself and other
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
configure {geode-name} to read/write-through to the backend Oracle Database when performing cache (Region) operations
by delegating to a Spring Data JPA Repository.
Suppose you use JPA and Hibernate to access data managed in an Oracle database. Then, you can configure {geode-name} to
read/write-through to the backend Oracle database when performing cache (Region) operations by delegating to a
Spring Data JPA Repository.
The configuration might look something like:
@@ -489,36 +487,36 @@ class SpringBootOracleDatabaseApacheGeodeApplication {
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`,
the `InlineCachingRegionConfigurer` configure and adapts the Spring Data `CrudRepository` as a `CacheLoader` and
`CacheWriter` registered on the region (for example, `Customers`) to enable inline caching functionality.
Given a `Predicate` to express the criteria used to match the target Region by name and a Spring Data `CrudRepository`,
the `InlineCachingRegionConfigurer` configures and adapts the Spring Data `CrudRepository` as a `CacheLoader`
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
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
database. However, you can inject any Spring Data repository for any data store (Redis, MongoDB, and others) that supports
the Spring Data repository abstraction.
In this example, we used JPA and Spring Data JPA to store and retrieve data stored in the cache (Region) to and from
a backend database. However, you can inject any Spring Data Repository for any data store (Redis, MongoDB, and others)
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,
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,
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
from the SBDG test suite. A dedicated sample will be provided in a future release.
TIP: To see a similar implementation of Inline caching with a database (an in-memory HSQLDB database) in action, 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 from the SBDG test suite. A dedicated sample will be provided in a future release.
[[geode-caching-provider-inline-caching-asynchronous]]
===== Asynchronous Inline Caching
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
from the cache to the backend data store periodically, you can employ asynchronous (write-behind) inline caching.
If consistency between the cache and your external data source is not a concern, and you need only write from the cache
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
cache operation. As a result, the backend data store is in an "`eventually consistent`" state, since the cache is
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
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.
@@ -533,20 +531,19 @@ batch updates.
[[geode-caching-provider-inline-caching-asynchronous-asynceventlistener]]
====== 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
the following yourself:
If you were to configure asynchronous, write-behind Inline caching by hand, you would need to do the following yourself:
1. Implement an `AsyncEventListener` to write to an external data source on cache events.
2. Configure, create, 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.
. Implement an `AsyncEventListener` to write to an external data source on cache events.
. Configure and register the listener with an `AsyncEventQueue` (AEQ).
. 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
is that with more moving parts, it is easier to make errors.
The advantage of this approach is that you have access to and control over low-level configuration details.
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:
.Example `AsyncEventListener` for Async _Inline Caching_
.Example `AsyncEventListener` for Asynchronous, Write-Behind Inline Caching
====
[source,java]
----
@@ -562,7 +559,7 @@ class ExampleAsyncEventListener implements AsyncEventListener {
@Override
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
}
@@ -570,14 +567,14 @@ class ExampleAsyncEventListener implements AsyncEventListener {
----
====
NOTE: Instead of directly injecting a `DataSource` into your `AsyncEventListener`, you could use JDBC,
Spring's `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.
NOTE: Instead of directly injecting a `DataSource` into your `AsyncEventListener`, you could use JDBC, Spring's
`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.
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
that will be the source of the cache events we want to persist asynchronously (step 3):
Then we need to register this listener with an `AsyncEventQueue` (step 2 from the procedure shown earlier) and attach it
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]
----
@@ -587,7 +584,7 @@ class GeodeConfiguration {
@Bean
DataSource exampleDataSource() {
// Configure and construct a data store specific DataSource
// Construct and configure a data store specific DataSource
}
@Bean
@@ -627,7 +624,7 @@ class GeodeConfiguration {
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.
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.
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]]
====== 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
as follows:
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 as follows:
.Using SBDG to configure Asynchronous (Write-Behind) Inline Caching
.Using SBDG to configure Asynchronous, Write-Behind Inline Caching
====
[source,java]
----
@@ -666,8 +664,8 @@ class ExampleSpringBootApacheGeodeAsyncInlineCachingApplication {
====
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
configure asynchronous inline caching functionality.
to programmatically express more powerful matching logic and identify the target Region (by name) on which to configure
asynchronous Inline caching functionality.
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
@@ -682,22 +680,21 @@ With the power of Spring Boot auto-configuration and SBDG, the configuration is
[[geode-caching-provider-inline-caching-asynchronous-listener]]
====== About `RepositoryAsyncEventListener`
The SBDG `RepositoryAsyncEventListener` class is the magic sauce behind the integration of the cache with an external
data source.
The SBDG `RepositoryAsyncEventListener` class is the magic ingredient behind the integration of the cache with
an external data source.
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
`CrudRepository`. The listener supports any external data source supported by Spring Data's
repository abstraction.
`CrudRepository`. The listener supports any external data source supported by Spring Data's 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
will be "`eventually consistent`".
will be "eventually consistent".
Given the complex nature of "`eventually consistent`" systems and asynchronous concurrent processing, the
`RepositoryAsyncEventListener` lets you register a custom `AsyncEventErrorHandler` to handle the errors
that occur during processing of `AsyncEvents`, perhaps due to a faulty backend data-store data-access operation
(such as `OptimisticLockingFailureException`), in an application-relevant way.
Given the complex nature of "eventually consistent" systems and asynchronous concurrent processing, the
`RepositoryAsyncEventListener` lets you register a custom `AsyncEventErrorHandler` to handle the errors that occur
during processing of `AsyncEvents`, perhaps due to a faulty backend data store data access operation (such as
`OptimisticLockingFailureException`), in an application-relevant way.
The `AsyncEventErrorHandler` interface is a `java.util.function.Function` implementation and `@FunctionalInterface`
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 event.
the `AsyncEvent`.
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
able to handle the error or not:
method to handle the error with application-specific actions. The handler returns a `Boolean` to indicate whether it
was able to handle the error or not:
.Custom `AsyncEventErrorHandler` implementation
====
@@ -729,11 +726,14 @@ class CustomAsyncEventErrorHandler implements AsyncEventErrorHandler {
if (error.getCause() instanceof OptimisticLockingFailureException) {
// 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) {
// 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;
@@ -760,8 +760,7 @@ class GeodeConfiguration {
@Bean
AsyncInlineCachingRegionConfigurer asyncInlineCachingRegionConfigurer(
CrudRepository<?, ?> repository,
CustomAsyncEventErrorHandler errorHandler
) {
CustomAsyncEventErrorHandler errorHandler) {
return AsyncInlineCachingRegionConfigurer.create(repository, "Example")
.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)`].
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()`.
`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()`.
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
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
provide implementations for the `cacheProcess(:AsyncEvent)` and `doRepositoryOp(entity)` methods.
NOTE: The `AsyncEventOperationRepositoryFunction.apply(:AsyncEvent)` method is already implemented in terms of
`canProcess(:AsyncEvent)`, `resolveEntity(:AsyncEvent)`, `doRepositoryOp(entity)`, and catching and handling any
`Throwable` (errors) by calling the configured `AsyncEventErrorHandler`.
`canProcess(:AsyncEvent)`, `resolveEntity(:AsyncEvent)`, `doRepositoryOp(entity)`, and catching and handling
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)`
method:
@@ -824,7 +824,7 @@ method:
----
@Component
class InvalidateAsyncEventRepositoryFunction
extends RepositoryAsyncEventListener.AbstractAsyncEventOperationRepositoryFunction<?, ?> {
extends RepositoryAsyncEventListener.AbstractAsyncEventOperationRepositoryFunction<?, ?> {
InvalidateAsyncEventRepositoryFunction(RepositoryAsyncEventListener<?, ?> listener) {
super(listener);
@@ -845,22 +845,23 @@ class InvalidateAsyncEventRepositoryFunction
----
====
You can then register your user-defined, `AsyncEventOperationRepositoryFunction`
(that is, `InvalidateAsyncEventRepositoryFunction`) with the `RepositoryAsyncEventListener` by using the
`AsyncInlineCachingRegionConfigurer`:
You can then register your user-defined, `AsyncEventOperationRepositoryFunction` (that is,
`InvalidateAsyncEventRepositoryFunction`) with the `RepositoryAsyncEventListener` by using
the `AsyncInlineCachingRegionConfigurer`:
.Configuring a user-defined `AsyncEventOperationRepositoryFunction`
====
[source,java]
----
import org.springframework.geode.cache.RepositoryAsyncEventListener;@Configuration
import org.springframework.geode.cache.RepositoryAsyncEventListener;
@Configuration
class GeodeConfiguration {
@Bean
AsyncInlineCachingRegionConfigurer asyncInlineCachingRegionConfigurer(
CrudRepository<?, ?> repository,
CustomerAsyncEventErrorHandler errorHandler
) {
CustomAsyncEventErrorHandler errorHandler ) {
return AsyncInlineCachingRegionConfigurer.create(repository, "ExampleRegion")
.applyToListener(listener -> {
@@ -886,44 +887,44 @@ the default behavior for these cache operations handled by SBDG.
[[geode-caching-provider-inline-caching-asynchronous-region-configurer]]
====== 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.
SBDG's lets you intercept and post-process the `AsyncEventListener` (such as `RepositoryAsyncEventListener`), the
`AsyncEventQueueFactory` and even the `AsyncEventQueue` created by the `AsyncInlineCachingRegionConfigurer`
SBDG's lets you intercept and post-process the `AsyncEventListener` (such as `RepositoryAsyncEventListener`),
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`])
during Spring `ApplicationContext` bean initialization.
The `AsyncInlineCachingRegionConfigurer` class provides the following builder methods to intercept and post-process
any of the following {geode-name} objects:
The `AsyncInlineCachingRegionConfigurer` class provides the following builder methods to intercept and post-process any
of the following {geode-name} objects:
* `applyToListener(:Function<AsyncEventListener, AsyncEventListener>)`
* `applyToQueue(:Function<AsyncEventQueue, AsyncEventQueue>)`
* `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.
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
Aspect-Oriented Programming (AOP) and the https://en.wikipedia.org/wiki/Decorator_pattern[decorator software design pattern].
Essentially, the returned object can be anything you want. This is the fundamental premise behind Aspect-Oriented
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 {geode-name} objects created by the listener.
The `apply*` methods and the supplied `Function` let you decorate, enhance, post-process, or otherwise modify
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]
as well and is, therefore, flexibly extensible.
and is, therefore, flexibly extensible.
[[geode-caching-provider-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,
and user demographic: active-active and active-passive.
As described earlier, there are two configuration arrangements, depending on your application usage patterns,
requirements and user demographic: active-active and active-passive.
Multi-site caching, along with active-active and active-passive configuration arrangements, are described
in more detail in the sample link:guides/caching-multi-site.html[guide]. Also, be sure to review the Sample
Multi-site caching, along with active-active and active-passive configuration arrangements, are described in more detail
in the sample link:guides/caching-multi-site.html[guide]. Also, be sure to review the sample
{github-samples-url}/caching/multi-site[code].
[[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.
As you can imagine, given that cache entries are stored in-memory, it becomes important to monitor and manage the
available memory wisely. After all, by default, {geode-name} stores data in the JVM Heap.
As you can imagine, given that cache entries are stored in-memory, it becomes important to manage and monitor
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
{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],
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],
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
{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
{spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[configuration options] available.
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 to you.
[[geode-caching-provider-disable]]
=== Disable Caching
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
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.
{spring-framework-docs}/integration.html#cache[Spring's Cache Abstraction] using {geode-name}. In certain cases,
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.
Either way, you can specifically call out your Spring cache abstraction provider by using the `spring.cache.type` property
in `application.properties`:
Either way, you can specifically call out your Spring Cache Abstraction provider by using the `spring.cache.type`
property in `application.properties`:
.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
do the following:
If you prefer not to use Spring's Cache Abstraction to manage your Spring Boot application's state at all, then set
the `spring.cache.type` property to "none":
.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]
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
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
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
{apache-geode-javadoc}/org/apache/geode/cache/client/ClientCache.html[`ClientCache`] instance that you get by declaring
Spring Boot for {geode-name} on your application classpath.
{apache-geode-javadoc}/org/apache/geode/cache/client/ClientCache.html[`ClientCache`] instance
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
building cache client applications deployed in an {geode-name}
It is assumed that most application developers who use Spring Boot to build applications backed by {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].
The client/server topology is the most common and traditional architecture employed by enterprise applications that
use {geode-name}.
The client/server topology is the most common and traditional architecture employed by enterprise applications
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 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
`localhost` and listen on the default `CacheServer` port, `40404`.
Your application now has a `ClientCache` instance that can connect to an {geode-name} server running on `localhost`
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.
However, it is perfectly valid to create a `ClientCache` instance and perform data access operations by using `LOCAL`
Regions. This is useful during development.
By default, an {geode-name} server (that is, `CacheServer`) must be running for the application to use the `ClientCache`
instance. However, it is perfectly valid to create a `ClientCache` instance and perform data access operations by using
`LOCAL` Regions. This is useful during development.
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`]
@@ -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].
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
are configuring additional {geode-name} objects (regions, indexes, and so on) or are using those objects indirectly
in your applications. However, it is possible to do so if and when needed.
application components (for example, `@Service` or `@Repository` beans defined in a Spring `ApplicationContext`),
whether you are configuring additional {geode-name} objects (Regions, Indexes, and so on) or are using those objects
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
{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?
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]:
> 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`
instance, declare your intention with either SDG's
If your application requirements demand you use Spring Boot to configure and bootstrap an embedded peer `Cache` instance,
declare your intention with either SDG's
{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 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.
By explicitly declaring the `@CacheServerApplication` annotation, you tell Spring Boot that you do not want
the default `ClientCache` instance but rather want an embedded peer `Cache` instance with a `CacheServer` component,
which enables connections from `ClientCache` apps.
By explicitly declaring the `@CacheServerApplication` annotation, you tell Spring Boot that you do not want the default
`ClientCache` instance but rather want an embedded peer `Cache` instance with a `CacheServer` component, which enables
connections from `ClientCache` applications.
You can also enable two other {geode-name} services:
* An embedded _Locator_, which allows clients or even other peers
to "`locate`" servers in the cluster.
* An embedded _Manager_, which allows the {geode-name} application process
to be managed and monitored by using {apache-geode-docs}/tools_modules/gfsh/chapter_overview.html[Gfsh], {geode-name}'s
command-line shell:
* An embedded _Locator_, which allows clients or even other peers to locate servers in the cluster.
* An embedded _Manager_, which allows the {geode-name} application process to be managed and monitored by using
{apache-geode-docs}/tools_modules/gfsh/chapter_overview.html[Gfsh], {geode-name}'s command-line shell tool:
.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]
----
@@ -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]
@@ -189,7 +188,7 @@ gfsh>list members
------------------------------------------- | --------------------------------------------------------------------------
SpringBootApacheGeodeCacheServerApplication | 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:29798)<ec><v0>:1024
gfsh>
gfsh>describe member --name=SpringBootApacheGeodeCacheServerApplication
Name : SpringBootApacheGeodeCacheServerApplication
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,
{geode-name} `CacheServer` application. These additional servers started in Gfsh know about the Spring Boot,
{geode-name} server because of the embedded lcator service, which is running on `localhost` and listening on
the default locator port, `10334`:
You can even start additional servers in Gfsh. These additional servers connect to your Spring Boot configured
and bootstrapped {geode-name} `CacheServer` application. These additional servers started in Gfsh know about
the Spring Boot, {geode-name} server because of the embedded Locator service, which is running on `localhost`
and listening on the default Locator port, `10334`:
====
[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
and bootstrapped Spring Boot, {geode-name} server application to an existing cluster. You can start the cluster in Gfsh
with the following commands (shown with partial typical output):
Perhaps you want to start the other way around. You may need to connect a Spring Boot configured and bootstrapped
{geode-name} server application to an existing cluster. You can start the cluster in Gfsh with the following commands
(shown with partial typical output):
====
[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:
.Spring Boot, {geode-name} `CacheServer` Application connecting to an external cluster
.Spring Boot {geode-name} `CacheServer` Application connecting to an external cluster
====
[source,java]
----
@@ -303,10 +302,11 @@ public class SpringBootApacheGeodeCacheServerApplication {
====
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,
you should see output similar to the following when you run the `list members` command:
After running your Spring Boot {geode-name} `CacheServer` application again and executing the `list members` command
in Gfsh again, you should see output similar to the following:
====
[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
and Gfsh server formed a cluster.
In both scenarios, the Spring Boot configured and bootstrapped {geode-name} server, the Gfsh Locator and Gfsh server
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
to form a small cluster while developing. Spring profiles make it far simpler and much faster to
configure and start a small cluster.
to form a small cluster while developing. Spring profiles make it far simpler and much faster to configure and start
a small cluster.
Also, approach enables rapidly prototyping, testing, and debugging of your entire end-to-end application
and system architecture, all right from the comfort and familiarity of your IDE. No additional tooling
(such as Gfsh) or knowledge is required to get started quickly and easily. Just build and run.
Also, this approach enables rapidly prototyping, testing, and debugging your entire end-to-end application
and system architecture right from the comfort and familiarity of your IDE. No additional tooling (such as Gfsh)
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,
especially if you start multiple instances. Otherwise, you are likely to run into a `java.net.BindException`
due to port conflicts.
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 on the same machine. Otherwise, you are likely to run into
a `java.net.BindException` caused by port conflicts.
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
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
clients locate a cluster of {geode-name} servers to manage data. Many cache clients can connect to the same cluster
to share data. Running multiple clients is common in a Microservices architecture where you need to scale-up
the number of application instances to satisfy the demand.
An {geode-name} Locator is a location-based service or, more typically, a standalone process that lets clients locate
a cluster of {geode-name} servers to manage data. Many cache clients can connect to the same cluster to share data.
Running multiple clients is common in a Microservices architecture where you need to scale-up the number of application
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
pooled system resources (memory, CPU, and disk). A locator maintains metadata that is sent to the clients to
enable such capabilities as single-hop data access, routing data access operations to the data node in the cluster
maintaining the data of interests. A locator also maintains load information for servers in the cluster, which enables
the load to be uniformly distributed across the cluster while also providing fail-over services to a redundant member
if the primary fails. A locator provides many more benefits, and we encourage you to read
the {apache-geode-docs}/configuring/running/running_the_locator.html[documentation] for more details.
An {geode-name} Locator is also used by joining members of an existing cluster to scale-out and increase capacity of
the logically pooled system resources (memory, CPU, network and disk). A Locator maintains metadata that is sent to
the clients to enable such capabilities as single-hop data access to route data access operations to the data node
in the cluster maintaining the data of interests. A Locator also maintains load information for servers in the cluster,
which enables the load to be uniformly distributed across the cluster while also providing fail-over services to a
redundant member if the primary fails. A Locator provides many more benefits, and we encourage you to read the
{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
by using the SDG `@EnableLocator` annotation:
As shown earlier, you can embed a Locator service within either a Spring Boot peer `Cache` or a `CacheServer`
application by using the SDG `@EnableLocator` annotation:
.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
the 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
higher degree of availability (HA) through redundancy.
However, it is more common to start standalone Locator JVM processes. This is useful when you want to increase the
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 or partition, having multiple Locators
provides a higher degree of availability (HA) through redundancy.
However, if all Locators in the cluster go down, the cluster still remains intact.
You cannot add more peer members (that is, scale-up the number of data nodes in the cluster)
or connect any more clients. If all the locators in the cluster go down, it is safe to restart them
only after a thorough diagnosis.
Even if all Locators in the cluster go down, the cluster still remains intact. You cannot add more peer members
(that is, scale-up the number of data nodes in the cluster) or connect any more clients, but the cluster is fine.
If all the locators in the cluster go down, it is safe to restart them only after a thorough diagnosis.
NOTE: Once a client receives metadata about the cluster of servers, all data-access operations are sent directly
to servers in the cluster, not a locator. Therefore, existing, connected clients remain connected and operable.
NOTE: Once a client receives metadata about the cluster of servers, all data-access operations are sent directly to
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:
.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`
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`
and not a `ClientCache`, `CacheServer`, or peer `Cache` application. If you need the application to function as a
peer `Cache`, perhaps with an embedded `CacheServer` components and embedded locator, you need to follow
the approach shown earlier: using the `@EnableLocator` annotation with either the `@PeerCacheApplication`
or `@CacheServerApplication` annotation.
NOTE: If your `@SpringBootApplication` class is annotated with `@LocatorApplication`, it must be a `Locator` and not
a `ClientCache`, `CacheServer`, or peer `Cache` application. If you need the application to function as a peer `Cache`,
perhaps with embedded `CacheServer` components and an embedded Locator, you need to follow the approach shown earlier:
using the `@EnableLocator` annotation with either the `@PeerCacheApplication` or `@CacheServerApplication` annotation.
With our Spring Boot, {geode-name} locator application, we can connect both configured and bootstrapped Spring Boot
peer members (peer `Cache`, `CacheServer` and `Locator` applications) as well as Gfsh started locators and servers.
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.
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
====
@@ -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
for the application main class: `-Dspring.data.gemfire.locator.name=SpringLocatorOne`. We name the second
locator application instance `SpringLocatorTwo`.
for the main application class: `-Dspring.data.gemfire.locator.name=SpringLocatorOne`. We name the second Locator
application instance `SpringLocatorTwo`.
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.
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.
For our first locator application instance (`SpringLocatorOne`), we also enable the manager profile so that
we can connect to the locator by using Gfsh.
For our first Locator application instance (`SpringLocatorOne`), we also enable the "manager" profile so that
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`
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`
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]
----
@@ -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
the cluster of Locators by using Gfsh:
Next, start up the second Locator application instance (you should see log output similar to the preceding list).
Then connect to the cluster of Locators by using Gfsh:
.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
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
====
@@ -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`
@@ -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
====
@@ -656,19 +655,19 @@ for {geode-name} (SBDG) in particular, make doing so easy.
[[geode-manager-applications]]
=== Building Manager Applications
As discussed in the previous sections, you can enable a configured and bootstrapped Spring Boot,
{geode-name} peer member node in the cluster to function as a manager.
As discussed in the previous sections, you can enable a Spring Boot configured and bootstrapped {geode-name}
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
be managed and monitored by using JMX-based tools, such as Gfsh, JConsole, or JVisualVM. Any tool
that uses the JMX API can connect to and manage an {geode-name} cluster for whatever purpose.
An {geode-name} Manager is a peer member node in the cluster that runs the management service, letting the cluster
be managed and monitored with JMX-based tools, such as Gfsh, JConsole, or JVisualVM. Any tool using the JMX API
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
may function as managers. Therefore, a `ClientCache` application cannot be a manager.
Like Locators, the cluster may have more than one Manager for redundancy. Only server-side, peer member nodes
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
====
@@ -710,22 +709,22 @@ class LocatorManagerApplication {
====
#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.
#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
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html[`@EnableManager` annotation]
for additional configuration options.
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
the embedded HTTP service in the manager.
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 required dependencies are:
@@ -750,10 +749,12 @@ and `spring-boot-starter-jetty` dependencies.
Optionally, you may also include the `geode-pulse` dependency, as follows:
.Additional, optional Manager depdendencies expressed in Gradle
====
[source,groovy]
----
runtime "org.apache.geode:geode-pulse"
----
====
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

View File

@@ -5,36 +5,36 @@
:pcc-name: Pivotal Cloud Cache
: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.
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
to one or more instances of the {pcc-name} (PCC) service.
In most cases, when you deploy (that is, `cf push`) your Spring Boot applications to {pcf-name} (PCF), you bind
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
{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
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.
[[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
to a {pcc-name} service instance.
By default, Spring Boot applications run as a `cluster_operator` role-based user in {pcf-name} when the application
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
the PCC service instance. A `cluster_operator` has read and write access to all the data, can modify the schema
(for example, create and destroy regions, add and remove indexes, change eviction or expiration policies, and so on), start and stop servers
in the PCC cluster, or even modify permissions.
the PCC service instance. A `cluster_operator` has read and write access to all the data, can modify the schema (for
example, create and destroy Regions, add and remove Indexes, change eviction or expiration policies, and so on), start
and stop servers in the PCC cluster, or even modify permissions.
.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
be sent from the client to the server. Enabling configuration metadata to be sent from the client to the server is a
useful development-time feature and is as simple as annotating your main `@SpringBootApplication` class with
the `@EnableClusterConfiguration` annotation:
One of the reasons why Spring Boot applications default to running as a `cluster_operator` is to allow configuration
metadata to be sent from the client to the server. Enabling configuration metadata to be sent from the client to the
server is a useful development-time feature and is as simple as annotating your main `@SpringBootApplication` class
with the `@EnableClusterConfiguration` annotation:
.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
servers in the PCC cluster. {geode-name} requires matching regions by name on both the client and the servers in order for
clients to send and receive data to and from the cluster.
With `@EnableClusterConfiguration`, Region and OQL Index configuration metadata that is defined on the client can be
sent to servers in the PCC cluster. {geode-name} requires matching Regions by name on both the client and the servers
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
annotation and declare the `@EnableEntityDefinedRegions` annotation on the main `@SpringBootApplication`
class in conjunction with the `@EnableClusterConfiguration` annotation, not only does SBDG create the required
client region, but it also sends the configuration metadata for this region to the servers in the cluster to create
the matching, required server region, where the data for your application entity is managed.
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` class
in conjunction with the `@EnableClusterConfiguration` annotation, not only does SBDG create the required client Region,
but it also sends the configuration metadata for this Region to the servers in the cluster to create the matching,
required server Region, where the data for your application entity is managed.
****
However...
> 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
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
permissions by using {pcf-name} AppsManager while provisioning the PCC service instance to which the Spring Boot app
is bound.
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
application is bound.
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.
If the `read-only-user` role is properly configured with read-only permissions as the name implies, we could
configure our Spring Boot application to run as `guest` with read-only access:
In the PCC service instance configuration metadata shown in the preceding example, we see a `guest` user with
the `read-only-user` role. If the `read-only-user` role is properly configured with read-only permissions as the name
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]
----
@@ -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
`securityUsername` attribute.
See the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#securityUsername--[Javadoc]
`securityUsername` attribute. See the
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html#securityUsername--[Javadoc]
for more details.
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
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.
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.
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.
[[cloudfoundry-cloudcache-security-auth-autoconfiguration-override]]
==== Overriding Authentication Auto-configuration
It should be generally understood that auto-configuration for client authentication is available only for managed
environments, such as {pcf-name}. When running in externally managed environments, you must explicitly set a username
and password to authenticate, as described in <<geode-security-auth-clients-non-managed>>.
It should be understood that auto-configuration for client authentication is available only for managed environments,
such as {pcf-name}. When running in externally managed environments, you must explicitly set a username and password
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:
@@ -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
are not extracted from the environment.
In this case, SBDG's auto-configuration for authentication is effectively disabled and security credentials are not
extracted from the environment.
[[cloudfoundry-cloudcache-serviceinstance-targeting]]
=== 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
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
application. This does not mean that it is not possible to use multiple PCC service instances with your Spring Boot app,
just that SBDG only auto-configures one service instance for you.
application. This does not mean that it is not possible to use multiple PCC service instances with your Spring Boot
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
multiple instances and want to target a specific PCC service instance to use.
You must select which PCC service instance your Spring Boot application automatically auto-configures for you when
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`:
@@ -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
to auto-configure.
If the PCC service instance identified by the property does not exist, SBDG throws
an `IllegalStateException` stating the PCC service instance by name could not be found.
If the PCC service instance identified by the property does not exist, SBDG throws an `IllegalStateException`
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.
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]]
=== Using Multiple {pcc-name} Service Instances
If you want to use multiple PCC service instances with your Spring Boot application, you need to configure
multiple connection `Pools` connected to each PCC service instance used by your Spring Boot application.
If you want to use multiple PCC service instances with your Spring Boot application, you need to configure multiple
connection `Pools` connected to each PCC service instance used by your Spring Boot application.
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
`application.properties`:
.Configuring Pool Locator connection endpoints
.Configuring Locator-based Pool connections
====
[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.
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.
A client region is then assigned the pool of connections that are used to send data to and from
the specific PCC service instance (cluster):
A client Region is then assigned the Pool of connections that are used to send data to and from the specific
PCC service instance (cluster):
.Assigning a pool to a client region
.Assigning a Pool to a client Region
====
[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
the {pcc-name} service instance and cluster in which the data for the client region resides.
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.
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
@@ -290,11 +291,11 @@ as discussed <<cloudfoundry-cloudcache-multiinstance-using,earlier>>.
[[cloudfoundry-geode]]
=== 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
connect your Spring Boot applications to an externally managed, standalone {geode-name} cluster.
Sometimes, it is desirable to deploy (that is, `cf push`) and run your Spring Boot applications in {pcf-name}
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
necessary`" goal. Regardless of your runtime choice, it should "`just work!`"
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!
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]]
==== 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
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.
You Spring Boot application can bind and use these services to accomplish its tasks.
Additionally, PCF Dev provides several services, such as MySQL, Redis, and RabbitMQ. You Spring Boot application
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,
since we are trying to build and run Spring Boot applications in a PCF environment but connect to an externally managed,
However, PCF Dev lacks the {pcc-name} service that is available in PCF. This is actually ideal for this exercise since
we are trying to build and run Spring Boot applications in a PCF environment but connect to an externally managed,
standalone {geode-name} cluster.
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]
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
with the file you acquired from the https://network.pivotal.io/products/pcfdev[download]:
To run PCF Dev, execute the following `cf` CLI command, replacing the path to the TGZ file with the file you acquired
from the https://network.pivotal.io/products/pcfdev[download]:
.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/
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.
[[cloudfoundry-geode-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
application connects and use it to manage its data.
Now that PCF Dev is set up and running, you need to start an external, standalone {geode-name} cluster to which our
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.
Then you must set the `$GEODE` environment variable. It is also convenient to add `$GEODE/bin` to your system `$PATH`.
You need to install a {apache-geode-website}/releases/[distribution] of {geode-name} on your computer. Then you must
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:
@@ -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
is also used by new servers that join a cluster as peer members, which lets the cluster be elastically scaled out
(or scaled down, as needed). A Geode server stores the data for the application.
A Locator is used by clients to discover and connect to servers in a cluster to manage its data. A Locator is also used
by new servers that join a cluster as peer members, which lets the cluster be elastically scaled out (or scaled down,
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.
The more locators and servers your cluster has, the more resilient it is to failure. However, you should
size your cluster accordingly, based on your application's needs, since there is overhead relative to the cluster size.
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 size your
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
====
@@ -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)
as well as on the server side (cluster). We cover this in more detail later in this chapter.
This is deliberate, since we are going to let the application drive its schema structure, both on the client
(application) as well as on the server-side (cluster). We cover this in more detail later in this chapter.
[[cloudfoundry-geode-cups]]
==== 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
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
the same capacity as you would {pcc-name} when running in a production-grade PCF environment, you need to create a
user-provided service for the standalone {geode-name} cluster.
As mentioned, PCF Dev offers MySQL, Redis and RabbitMQ services (among others). However, to use {geode-name} in the same
capacity as you would {pcc-name} when running in a production-grade PCF environment, you need to create a user-provided
service for the standalone {geode-name} cluster.
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
in the preceding `cf` CLI command.
The argument passed to the `-p` command-line option is a JSON document (object) containing the credentials
for our user-provided service.
The argument passed to the `-p` command-line option is a JSON document (object) containing the credentials for our
user-provided service.
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
in the _Gfsh_ `start locator` output shown in the preceding example.
We replaced the `<hostname>` placeholder with the IP address of our standalone {geode-name} Locator. You can find
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.
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]
----
@@ -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[]
By clicking on the "apacheGeodeService" service entry in the table, you can get all the service details,
such as the bound apps:
By clicking on the "apacheGeodeService" service entry in the table, you can get all the service details, such as
the bound apps:
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[]
This brief section did not cover all the capabilities of the Apps Manager.
We suggest you explore its UI to see all that is possible.
This brief section did not cover all the capabilities of the Apps Manager. We suggest you explore its UI to see all
that is possible.
TIP: You can learn more about CUPS in the
{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]]
==== 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
the https://github.com/jxblum/PCCDemo/tree/sbdg-doc-ref[PCCDemo] application, which is available in GitHub.
Any Spring Boot `ClientCache` application that uses SBDG works for this purpose. For this example, we use the
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]
----
@@ -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]
----
@@ -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]
----
@@ -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]
----
@@ -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
deployment descriptor:
Alternatively, you can create a YAML file (`manifest.yml` in `src/main/resources`) that contains
the deployment descriptor:
.Example YAML deployment descriptor file
.Example YAML deployment descriptor
====
[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
the `App` tab under your org and space:
You can also use Apps Manager to view application details and bind and unbind additional services.
Start by navigating to the `App` tab under your org and space:
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[]
You can also review the app `Settings`. Specifically, we are looking at the configuration of the app once it is bound to
the `apacheGeodeService`, as seen in the `VCAP_SERVICES` environment variable:
You can also review the application `Settings`. Specifically, we are looking at the configuration of the applicatinon
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[]
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
the amount of boilerplate code and configuration changes when you migrate between different CloudFoundry environments,
even https://www.cloudfoundry.org/[Open Source CloudFoundry].
to the {pcc-name} service when deploying the same application to {pcf-name}. This is actually key if you want to
minimize the amount of boilerplate code and configuration changes when you migrate between different 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,
in whatever context your application lands, even if it changes later. If you follow the steps in this documentation,
you can realize that goal.
Again, SBDG's goal is to simply the effort for you to build, run, and manage your application, in whatever context
your application lands, even if it changes later. If you follow the steps in this documentation, you can realize
that goal.
[[cloudfoundry-geode-app-run]]
==== 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]
----
@@ -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
the application log file.
Alternatively, you can also start the application from Apps Manager. This is convenient, since you can then tail
and monitor the application log file.
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.
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
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[]
You can also access the same data from the Gfsh command-line tool. However, the first thing to observe
is that our application informed the cluster that it needed a region called `Books`:
You can also access the same data from the Gfsh command-line tool. However, the first thing to observe is that our
application informed the cluster that it needed a Region called `Books`:
.Books Region
====
@@ -819,12 +821,12 @@ Rows : 1
[[cloudfoundry-geode-summary]]
=== Summary
The ability to deploy Spring Boot, {geode-name} `ClientCache` applications to {pcf-name} yet connect your app to an
externally managed, standalone {geode-name} cluster is powerful.
The ability to deploy Spring Boot, {geode-name} `ClientCache` applications to {pcf-name} yet connect your application to
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
Cloud-Native platforms such as {pcf-name} and using services such as {pcc-name}.
Indeed, this is a useful arrangement and stepping stone for many users as they begin their journey towards Cloud-Native
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
managed and production-grade {pcf-name} environment, and SBDG figures out what to do, leaving you to focus entirely
on your application.
Later, when you need to work with real (rather than sample) applications, you can migrate your Spring Boot applications
to a fully managed and production-grade {pcf-name} environment, and SBDG figures out what to do, leaving you to focus
entirely on your application.

View File

@@ -1,8 +1,8 @@
[[geode-auto-configuration-annotations]]
== Auto-configuration vs. Annotation-based configuration
:geode-name: {apache-geode-name}
:vmw-gemfire-name: VMware Tanzu GemFire
:vmw-tas-name: VMware Tanzu Application Service
:vmw-gemfire-name: {pivotal-gemfire-name}
: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
@@ -16,29 +16,29 @@ which shows the auto-configuration provided by Spring Boot for {geode-name} in a
[[geode-autoconfiguration-annotations-background]]
=== Background
To help answer this question, we must start by reviewing the complete collection of available Spring Data for {geode-name}
(SDG) annotations. These annotations are provided in the
To help answer this question, you must start by reviewing the complete collection of available Spring Data for
{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`]
package. Most of the pertinent annotations begin with `@Enable...`, except for the base annotations:
`@ClientCacheApplication`, `@PeerCacheApplication`, and `@CacheServerApplication`.
package. Most of the essential annotations begin with `@Enable...`, except for the base annotations:
`@ClientCacheApplication`, `@PeerCacheApplication` and `@CacheServerApplication`.
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
{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
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
accomplishes this by applying sensible defaults so that application developers need not know, or even have to learn,
all the intricate configuration details and tooling provided by {geode-name} to accomplish simple tasks, such as building a
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, all
the intricate configuration details and tooling provided by {geode-name} to accomplish simple tasks, such as building a
prototype.
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.
So, SDG is all about "`choice`" and SBDG is all about "`convention`". Together these frameworks provide application
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].
[[geode-autoconfiguration-annotations-conventions]]
@@ -49,18 +49,18 @@ Currently, SBDG provides auto-configuration for the following features:
* `ClientCache`
* Caching with Spring's cache abstraction
* Continuous Query
* Function execution and implementation
* Function Execution and Implementation
* Logging
* PDX
* `GemfireTemplate`
* Spring Data repositories
* Spring Data Repositories
* Security (Client/server auth and SSL)
* 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`
* `@EnableGemfireCaching` (or by using Spring Framework's `@EnableCaching`)
* `@EnableGemfireCaching` (or by using Spring Framework's `@EnableCaching` annotation)
* `@EnableContinuousQueries`
* `@EnableGemfireFunctionExecutions`
* `@EnableGemfireFunctions`
@@ -72,7 +72,7 @@ This means the following SDG Annotations are not required to use the features ab
* `@EnableGemFireHttpSession`
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.
[[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]]
==== Caches
By default, SBDG provides you with a `ClientCache` instance. SBDG accomplishes this by annotating
an auto-configuration class with `@ClientCacheApplication` internally.
By default, SBDG provides you with a `ClientCache` instance. SBDG accomplishes this by annotating an auto-configuration
class with `@ClientCacheApplication` internally.
By convention, we assume most application developers' are developing Spring Boot applications by using
{geode-name} as "`client`" applications in {geode-name}'s client/server topology. This is especially true as users
migrate their applications to a managed cloud environment.
By convention, we assume most application developers' are developing Spring Boot applications by using {geode-name}
as "`client`" applications in {geode-name}'s client/server topology. This is especially true as users migrate their
applications to a managed cloud environment.
Still, you can "override" the default settings and declare your Spring applications to be actual peer `Cache`
members of a cluster, instead:
Still, you can "`override`" the default settings (convention) and declare your Spring applications to be actual peer
`Cache` members (nodes) of a {geode-name} cluster, instead:
.Spring Boot, {geode-name} Peer `Cache` Application
====
[source,java]
----
@SpringBootApplication
@CacheServerApplication
class MySpringBootPeerCacheServerApplication { }
class SpringBootApacheGeodePeerCacheServerApplication { }
----
====
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`
instance hosting an embedded `CacheServer` that allows client connections.
does not provide you with a `ClientCache` instance by default, because you have informed SBDG of exactly what you want:
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
without explicitly declaring the `@ClientCacheApplication` annotation?`"
First, you can "`customize`" the `ClientCache` instance by explicitly declaring the
`@ClientCacheApplication` annotation in your Spring Boot application configuration and setting specific attributes
as needed. However, you should be aware that, by explicitly declaring this annotation, (or, by default, any of the other
auto-configured annotations), you assume all the responsibility that comes with it, since you have
effectively overridden the auto-configuration. One example of this is security, which we touch on more later.
First, you can "`customize`" the `ClientCache` instance by explicitly declaring the `@ClientCacheApplication` annotation
in your Spring Boot application configuration and setting specific attributes as needed. However, you should be aware
that, by explicitly declaring this annotation, (or, by default, any of the other auto-configured annotations), you
assume all the responsibility that comes with it, since you have effectively overridden the auto-configuration. One
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
<<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]]
==== Security
As the `@ClientCacheApplication` annotation, the `@EnableSecurity` annotation is not strictly required, unless
you want to override and customize the defaults.
As with the `@ClientCacheApplication` annotation, the `@EnableSecurity` annotation is not strictly required, unless you
want to override and customize the defaults.
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`:
@@ -139,50 +140,49 @@ spring.data.gemfire.security.password=Secret
----
====
You need not explicitly declare the `@EnableSecurity` annotation just to specify security configuration
(such as username and password).
You need not explicitly declare the `@EnableSecurity` annotation just to specify security configuration (such as
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
and passwords, or otherwise. This is due, in part, because PCF supplies the security details in the VCAP environment
when the app is deployed to TAS and bound to services (such as {vmw-gemfire-name}).
and passwords, or otherwise. This is due, in part, because TAS supplies the security details in the VCAP environment
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,
you are now responsible for this configuration, and SBDG's auto-configuration no longer applies.
However, if you do explicitly declare the `@ClientCacheApplication` or `@EnableSecurity` annotations, you are now
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
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
completely shield you from the nuances of {geode-name}'s configuration.
This is entirely due to the internals of {geode-name}, because, in certain cases (such as security), not even Spring
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`)
is created. This is because security is enabled and configured during the "`construction`"
of the cache. Also,, the cache pulls the configuration from JVM System properties that must be set before the cache
is constructed.
You must configure both auth and SSL before the cache instance (whether a `ClientCache` or a peer `Cache`) is created.
This is because security is enabled and configured during the "`construction`" of the cache. Also,, the cache pulls
the configuration from JVM System properties that must be set before the cache is constructed.
Structuring the "`exact`" order of the auto-configuration classes provided by SBDG when the classes are triggered,
is no small feat. Therefore, it should come as no surprise to learn that the security auto-configuration classes
in SBDG must be triggered before the `ClientCache` auto-configuration class, which is why a `ClientCache` instance cannot
"`auto`" authenticate properly in PCC when the `@ClientCacheApplication` is explicitly declared without some assistance.
In other 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.
Structuring the "`exact`" order of the auto-configuration classes provided by SBDG when the classes are triggered, is no
small feat. Therefore, it should come as no surprise to learn that the security auto-configuration classes in SBDG must
be triggered before the `ClientCache` auto-configuration class, which is why a `ClientCache` instance cannot "`auto`"
authenticate properly in PCC when the `@ClientCacheApplication` is explicitly declared without some assistance. In other
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.
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.
[[geode-autoconfiguration-annotations-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.
Many of these features are enabled automatically by having SBDG or other libraries (such as Spring Session)
on the classpath or are enabled based on other annotations applied to beans in the Spring `ApplicationContext`.
Many of these features are enabled automatically by having SBDG or other libraries (such as Spring Session) on
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.
@@ -190,8 +190,8 @@ We review a few examples in the following sections.
==== Caching
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`"
caching and configures the SDG `GemfireCacheManager` for you.
SDG-specific `@EnableGemfireCaching` annotation in Spring configuration when you use SBDG. SBDG automatically
enables caching and configures the SDG `GemfireCacheManager` for you.
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
class CustomerService {
@Autowired
private CustomerRepository customerRepository;
@Autowired
private CustomerRepository customerRepository;
@Cacheable("CustomersByName")
public Customer findBy(String name) {
return customerRepository.findByName(name);
}
@Cacheable("CustomersByName")
public Customer findBy(String name) {
return customerRepository.findByName(name);
}
}
----
====
You need to create {geode-name} regions that back the caches declared in your application service
components (`CustomersByName` in the preceding example) by using Spring's Caching Annotations (such as `@Cacheable`), or alternatively,
JSR-107 JCache annotations (such as `@CacheResult`).
You need to create {geode-name} Regions that back the caches declared in your application service components
(`CustomersByName` in the preceding example) by using Spring's caching annotations (such as `@Cacheable`),
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)
====
@@ -229,16 +229,16 @@ class Application { }
----
====
`@EnableCachingDefinedRegions` is optional, provided for convenience, and complementary to caching when used
rather than being necessary.
`@EnableCachingDefinedRegions` is optional, provided for convenience, and complementary to caching when used rather than
being necessary.
See the <<geode-caching-provider,Reference Guide>> for more detail.
[[geode-autoconfiguration-annotations-extension-cq]]
==== Continuous Query
It is rarely, if ever, necessary to explicitly declare the SDG `@EnableContinuousQueries` annotation. Instead,
you should focus on defining your application queries and worry less about the plumbing.
It is rarely, if ever, necessary to explicitly declare the SDG `@EnableContinuousQueries` annotation. Instead, you
should focus on defining your application queries and worry less about the plumbing.
Consider the following example:
@@ -272,8 +272,10 @@ See the <<geode-continuous-query,Reference Guide>> for more detail.
==== Functions
You rarely, if ever, need to explicitly declare either the `@EnableGemfireFunctionExecutions`
or `@EnableGemfireFunctions` annotations. SBDG provides auto-configuration for both function implementations
and executions. You need to define the implementation:
or `@EnableGemfireFunctions` annotations. SBDG provides auto-configuration for both Function implementations
and executions.
You need to define the implementation:
.Function Implementation
====
@@ -282,10 +284,10 @@ and executions. You need to define the implementation:
@Component
class GeodeFunctions {
@GemfireFunction
Object exampleFunction(Object arg) {
// ...
}
@GemfireFunction
Object exampleFunction(Object arg) {
// ...
}
}
----
====
@@ -299,24 +301,25 @@ Then you need to define the execution:
@OnRegion(region = "Example")
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
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`
annotated main class.
The application Function implementations (POJOs) and executions (interfaces) should exist below
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]]
==== PDX
You rarely, if ever, need to explicitly declare the `@EnablePdx` annotation, since SBDG auto-configures PDX
by default. SBDG also automatically configures the SDG `MappingPdxSerializer` as the default `PdxSerializer`.
You rarely, if ever, need to explicitly declare the `@EnablePdx` annotation, since SBDG auto-configures PDX by default.
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>>
(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]]
==== Spring Data Repositories
You rarely, if ever, need to explicitly declare the `@EnableGemfireRepositories` annotation, since SBDG
auto-configures Spring Data (SD) repositories by default.
You rarely, if ever, need to explicitly declare the `@EnableGemfireRepositories` annotation, since SBDG auto-configures
Spring Data (SD) Repositories by default.
You need only define your repositories:
You need only define your Repositories:
.Customer's Repository
====
@@ -337,18 +340,18 @@ You need only define your repositories:
----
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
in the Spring `ApplicationContext`. The repositories can be injected into other application service components.
SBDG finds the Repository interfaces defined in your application, proxies them, and registers them as beans in
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
the entities used by your application and define the regions used by the SD repository infrastructure to persist
the entity's state. The `@EnableEntityDefinedRegions` annotation is optional, provided for convenience,
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 Spring Data Repository infrastructure to
persist the entity's state. The `@EnableEntityDefinedRegions` annotation is optional, provided for convenience,
and complementary to the `@EnableGemfireRepositories` annotation.
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`
* `@UseGemFireProperties`
None of these annotations are necessary and none are auto-configured by SBDG. They are at your
disposal you need them. This also means that none of these annotations are in conflict with
any SBDG auto-configuration.
None of these annotations are necessary and none are auto-configured by SBDG. They are at your disposal when and if you
need them. This also means that none of these annotations are in conflict with any SBDG auto-configuration.
[[geode-autoconfiguration-annotations-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
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`).
In other cases, you might also want to explicitly declare a complimentary annotation (such as `@EnableEntityDefinedRegions`)
for convenience, since SBDG provides no convention or "`opinion`".
In other cases, you might also want to explicitly declare a complimentary annotation
(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
lengths to shield you from as many details as possible, it is not feasible or practical to address all matters,
such as cache creation and security.
lengths to shield you from as many details as possible, it is not feasible or practical to address all matters, such as
cache creation and security.

View File

@@ -9,8 +9,8 @@ annotations are implicitly declared by Spring Boot for {geode-name}'s (SBDG) aut
* `@ClientCacheApplication`
* `@EnableGemfireCaching` (alternatively, Spring Framework's `@EnableCaching`)
* `@EnableContinuousQueries`
* `@EnableGemfireFunctionExecutions`
* `@EnableGemfireFunctions`
* `@EnableGemfireFunctionExecutions`
* `@EnableGemfireRepositories`
* `@EnableLogging`
* `@EnablePdx`
@@ -19,35 +19,35 @@ annotations are implicitly declared by Spring Boot for {geode-name}'s (SBDG) aut
* `@EnableGemFireHttpSession`
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
to _override_ Spring Boot's, and in particular, SBDG's auto-configuration. Otherwise, doing so is unnecessary.
since they are provided by SBDG already. The only reason you would explicitly declare any of these annotations is to
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].
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
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]
to see Spring Boot auto-configuration for {geode-name} in action.
[[geode-configuration-auto-customizing]]
=== 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?`"
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
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`
annotation throgh auto-configuration on your behalf. What do you do?
so that you can set the client member's name. However, SBDG has already implicitly declared the `@ClientCacheApplication`
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`
====
@@ -55,8 +55,8 @@ For example, to set the (client or peer) member's `name`, you can use the `@UseM
----
@SpringBootApplication
@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:
* Using the {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
durable clients with `@EnableDurableClient`).
* 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 the `@UseMemberName`
annotation or enabling durable clients with the `@EnableDurableClient` annotation).
* 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`).
@@ -101,12 +104,13 @@ TIP: For the complete list of documented properties, see <<geode-configuration-m
[[geode-configuration-auto-disabling]]
=== 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,
declare your intent in the `@SpringBootApplication` annotation:
In a nutshell, if you want to disable any auto-configuration provided by either Spring Boot or SBDG, declare your intent
in the `@SpringBootApplication` annotation:
.Disabling Specific Auto-configuration Classes
====
@@ -115,7 +119,7 @@ declare your intent in the `@SpringBootApplication` annotation:
@SpringBootApplication(
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.
In a nutshell, if you want to override the default auto-configuration provided by SBDG, you must annotate
your `@SpringBootApplication` class with your intent.
In a nutshell, if you want to override the default auto-configuration provided by SBDG, you must annotate your
`@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
====
@@ -139,7 +144,7 @@ For example, suppose you want to configure and bootstrap an {geode-name} `CacheS
----
@SpringBootApplication
@CacheServerApplication
class SpringBootCacheServerApplication {
class SpringBootApacheGeodeCacheServerApplication {
// ...
}
----
@@ -153,14 +158,16 @@ You can also explicitly declare the `@ClientCacheApplication` annotation on your
----
@SpringBootApplication
@ClientCacheApplication
class SpringBootClientCacheApplication {
class SpringBootApacheGeodeClientCacheApplication {
// ...
}
----
====
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
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]]
=== 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]]
=== 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>>.
[[geode-configuration-declarative-auto-configuration-clientcacheapplication]]
==== `@ClientCacheApplication`
NOTE: The {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.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/ClientCacheAutoConfiguration.html[`ClientCacheAutoConfiguration`] class
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}
<<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
dedicated cluster of {geode-name} servers that manage the data as part of a
Technically, this means building Spring Boot applications with an {geode-name} `ClientCache` instance connected to
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.
By way of example, this means you that need not explicitly declare and annotate your `@SpringBootApplication` class
with SDG's `@ClientCacheApplication` annotation, as the following negative example shows:
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 example shows:
.Do Not Do This
====
@@ -202,27 +210,27 @@ with SDG's `@ClientCacheApplication` annotation, as the following negative examp
----
@SpringBootApplication
@ClientCacheApplication
class SpringBootClientCacheApplication {
class SpringBootApacheGeodeClientCacheApplication {
// ...
}
----
====
SBDG's provided _Auto-configuration_ class is already meta-annotated with SDG's
`@ClientCacheApplication` annotation. Therefore, you need only:
SBDG's provided auto-configuration class is already meta-annotated with SDG's `@ClientCacheApplication` annotation.
Therefore, you need only do:
.Do This
====
[source,java]
----
@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]
and {spring-data-geode-docs-html}/#bootstrap-annotation-config-client-server-applications[client/server applications]
in particular.
@@ -230,11 +238,11 @@ in particular.
[[geode-configuration-declarative-auto-configuration-enablecaching]]
==== `@EnableGemfireCaching`
NOTE: The {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.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/CachingProviderAutoConfiguration.html[`CachingProviderAutoConfiguration`] class
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
in {spring-framework-docs}/integration.html#cache[Spring's cache abstraction], you need to:
If you used the core Spring Framework to configure {geode-name} as a caching provider in
{spring-framework-docs}/integration.html#cache[Spring's Cache Abstraction], you need to:
.Configuring caching using the Spring Framework
====
@@ -244,22 +252,23 @@ in {spring-framework-docs}/integration.html#cache[Spring's cache abstraction], y
@EnableCaching
class CachingUsingApacheGeodeConfiguration {
@Bean
GemfireCacheManager cacheManager(GemFireCache cache) {
@Bean
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]
----
@@ -273,7 +282,7 @@ class CachingUsingApacheGeodeConfiguration {
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]
----
@@ -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
the plumbing. You can then demarcate the service methods in your application that are good candidates for caching:
This lets you focus on the areas in your application that would benefit from caching without having to enable the
plumbing. You can then demarcate the service methods in your application that are good candidates for caching:
.Using caching in your application
====
@@ -294,27 +303,27 @@ the plumbing. You can then demarcate the service methods in your application tha
@Service
class CustomerService {
@Caching("CustomersByName")
Customer findBy(String name) {
// ...
}
@Caching("CustomersByName")
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]]
==== `@EnableContinuousQueries`
NOTE: The {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.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/ContinuousQueryAutoConfiguration.html[`ContinuousQueryAutoConfiguration`] class
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
{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
case, the method is an implementation of
{apache-geode-javadoc}/org/apache/geode/cache/query/CqListener.html[`CqListener`].
terminology, the method is an implementation of the
{apache-geode-javadoc}/org/apache/geode/cache/query/CqListener.html[`CqListener`] interface.
.Declare application CQs
====
@@ -323,32 +332,33 @@ case, the method is an implementation of
@Component
class MyCustomerApplicationContinuousQueries {
@ContinuousQuery("SELECT customer.* FROM /Customers customers"
+ " WHERE customer.getSentiment().name().equalsIgnoreCase('UNHAPPY')")
public void handleUnhappyCustomers(CqEvent event) {
// ...
}
@ContinuousQuery("SELECT customer.* "
+ " FROM /Customers customers"
+ " 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
predicate that describes the events of interests and implements the handler method to process the events (such as applying a credit
to the customer's account and following up in email).
As the preceding example shows, you can define the events you are interested in receiving by using an OQL query with a
finely tuned query predicate that describes the events of interests and implements the handler method to process the
events (such as applying a credit to the customer's account and following up in email).
TIP: See <<geode-continuous-query>> for more details.
[[geode-configuration-declarative-auto-configuration-enablefunctions]]
==== `@EnableGemfireFunctionExecutions` & `@EnableGemfireFunctions`
NOTE: The {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`]
and {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/config/EnableGemfireFunctions.html[`@EnableGemfireFunctions`] annotations.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/FunctionExecutionAutoConfiguration.html[`FunctionExecutionAutoConfiguration`] class
corresponds to both the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/function/config/EnableGemfireFunctionExecutions.html[`@EnableGemfireFunctionExecutions`]
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]
or {spring-data-geode-docs-html}/#function-implementation[implement] a `Function`, SBDG detects the function
definition and auto-configures it appropriately for use in your Spring Boot application. You need only define
the function execution or implementation in a package below the main `@SpringBootApplication` class:
or {spring-data-geode-docs-html}/#function-implementation[implement] a `Function`, SBDG detects the Function definition
and auto-configures it appropriately for use in your Spring Boot application. You need only define the Function
execution or implementation in a package below the main `@SpringBootApplication` class:
.Declare a Function Execution
====
@@ -377,7 +387,7 @@ package example.app.service;
class CustomerService {
@Autowired
private MyCustomerapplicationFunctions customerFunctions;
private MyCustomerApplicationFunctions customerFunctions;
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 function implementation for use (that is, to be called by a function execution).
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).
Doing so lets you focus on defining the logic required by your application and not worry about
how functions are registered, called, and so on. SBDG handles this concern for you.
Doing so lets you focus on defining the logic required by your application and not worry about how Functions
are registered, called, and so on. SBDG handles this concern for you.
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]]
==== `@EnableGemfireRepositories`
NOTE: The {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.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/GemFireRepositoriesAutoConfigurationRegistrar.html[`GemFireRepositoriesAutoConfigurationRegistrar`] class
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
your application to carry out its functions, not with how to create and perform them (for example, `Region.get(key)`
and `Region.put(key, obj)`) or execute them (for example, `Query.execute(arguments)`).
As with Functions, you need concern yourself only with the data access operations (such as basic CRUD and simple queries)
required by your application to carry out its operation, not with how to create and perform them (for example,
`Region.get(key)` and `Region.put(key, obj)`) or execute them (for example, `Query.execute(arguments)`).
Start by defining your Spring Data Repository:
@@ -421,13 +431,13 @@ package example.app.repo;
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
====
@@ -438,21 +448,22 @@ package example.app.sevice;
@Service
class CustomerService {
@Autowired
private CustomerRepository repository;
@Autowired
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`
class. Again, you are focusing only on the data access operations and queries required to carry out the functions
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 operatinons
of your application, nothing more.
TIP: See <<geode-repositories>> for more details.
@@ -460,15 +471,13 @@ TIP: See <<geode-repositories>> for more details.
[[geode-configuration-declarative-auto-configuration-enablelogging]]
==== `@EnableLogging`
NOTE: The {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.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/LoggingAutoConfiguration.html[`LoggingAutoConfiguration`] class
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
the events occurred. By default, SBDG auto-configures logging for {geode-name} with the default log-level,
`config`.
the events occurred. By default, SBDG auto-configures logging for {geode-name} with the default log-level, "`config`".
You can change an aspect of logging, such as the log-level, in Spring Boot
`application.properties`:
You can change any aspect of logging, such as the log-level, in Spring Boot `application.properties`:
.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
used to store the {geode-name} log files at runtime.
NOTE: The 'spring.data.gemfire.logging.level' property is an alias for `spring.data.gemfire.cache.log-level`.
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
logging provider (such as Logback) and configuration metadata appropriate for that logging provider so long as you 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
logging provider (such as Logback) and configuration metadata appropriate for that logging provider so long as you
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 will need the
`org.apache.logging.log4j:log4j-to-slf4j` adapter.
[[geode-configuration-declarative-auto-configuration-enablepdx]]
==== `@EnablePdx`
NOTE: The {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.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/PdxSerializationAutoConfiguration.html[`PdxSerializationAutoConfiguration`] class
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
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.
model object must be serializable. It would be painful to have to implement `java.io.Serializable` in every one of your
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
or even possible in other cases (such as when you use a third party library over which you have no control).
Furthermore, using Java Serialization may not be ideal (it may not be the most portable or efficient solution) in all
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
to be serializable and exist on the classpath for every place it is sent. Indeed, the final destination
may not even be a Java application. This is where {geode-name}
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 in every place it is sent. Indeed, the final destination may not even be
a Java application. This is where {geode-name}
{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
@@ -517,13 +528,13 @@ serialized. Instead, you can define your class type as follows:
@Region("Customers")
class Customer {
@Id
private Long id;
@Id
private Long id;
@Indexed
private String name;
@Indexed
private String name;
// ...
// ...
}
----
====
@@ -535,10 +546,11 @@ TIP: See <<geode-data-serialization>> for more details.
[[geode-configuration-declarative-auto-configuration-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
correspond to the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html[`@EnableSecurity`] annotation, but they apply
Security (specifically, Authentication and Authorization configuration) for both clients and servers.
correspond to the SDG {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableSecurity.html[`@EnableSecurity`] annotation,
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
{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.
You need not do anything.
NOTE: Authentication is even easier to configure in a managed environment, such as PCF when using PCC. You need not do
anything.
Authorization is configured on the server-side and is made simple with SBDG and the help of https://shiro.apache.org/[Apache Shiro].
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>>.
Authorization is configured on the server-side and is made simple with SBDG and the help of
https://shiro.apache.org/[Apache Shiro].
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.
[[geode-configuration-declarative-auto-configuration-enablessl]]
==== `@EnableSsl`
NOTE: The {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.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/SslAutoConfiguration.html[`SslAutoConfiguration`] class
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
cluster can be a real problem, especially to get correct from the start. So, it is something that SBDG makes
as simple as possible.
Configuring SSL for secure transport (TLS) between your Spring Boot, {geode-name} `ClientCache` application and an
{geode-name} cluster can be a real problem, especially to get right from the start. So, it is something that SBDG
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
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
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]]
==== `@EnableGemFireHttpSession`
NOTE: The {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.
NOTE: The SBDG {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/SpringSessionAutoConfiguration.html[`SpringSessionAutoConfiguration`] class
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
that you include the correct starter, such as `spring-geode-starter-session`:
Configuring {geode-name} to serve as the (HTTP) session state caching provider by using Spring Session requires that
you only include the correct starter, that is `spring-geode-starter-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,
{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
the right thing.
{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 the rest.
TIP: See <<geode-session>> for more details.
@@ -613,10 +625,10 @@ TIP: See <<geode-session>> for more details.
==== RegionTemplateAutoConfiguration
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
{geode-name} `Region` defined and declared in your Spring Boot application is still supplied by SBDG.
has no corresponding SDG annotation. However, the auto-configuration of a `GemfireTemplate` for every {geode-name}
`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
====
@@ -625,23 +637,22 @@ For example, you can define a region by using:
@Configuration
class GeodeConfiguration {
@Bean("Customers")
ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) {
@Bean("Customers")
ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) {
ClientRegionFactoryBean<Long, Customer> customersRegion =
new ClientRegionFactoryBean<>();
ClientRegionFactoryBean<Long, Customer> customersRegion =
new ClientRegionFactoryBean<>();
customersRegion.setCache(cache);
customersRegion.setShortcut(ClientRegionShortcut.PROXY);
customersRegion.setCache(cache);
customersRegion.setShortcut(ClientRegionShortcut.PROXY);
return customersRegion;
}
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`
====
@@ -656,7 +667,7 @@ class GeodeConfiguration {
====
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
====
@@ -665,21 +676,21 @@ Then SBDG supplies a `GemfireTemplate` instance that you can use to perform low-
@Repository
class CustomersDao {
@Autowired
@Qualifier("customersTemplate")
private GemfireTemplate customersTemplate;
@Autowired
@Qualifier("customersTemplate")
private GemfireTemplate customersTemplate;
Customer findById(Long id) {
return this.customerTemplate.get(id);
}
Customer findById(Long id) {
return this.customerTemplate.get(id);
}
}
----
====
You need not explicitly configure `GemfireTemplates` for each region to which you need low-level data access
(such as when you are not using the Spring Data Repository abstraction).
You need not explicitly configure `GemfireTemplates` for each Region to which you need low-level data access (such as
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.
TIP: See <<geode-data-access-region-templates>> for more details.

View File

@@ -3,52 +3,53 @@
:geode-name: {apache-geode-name}
The primary purpose of any software development framework is to help you be productive as quickly and as easily
as possible and to do so in a reliable manner.
The primary purpose of any software development framework is to help you be productive as quickly and as easily as
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
behaviors are predictable. This provided convenience not only helps you hit the ground running in the right
direction sooner but increases your focus on the application domain so that you can better understand the problem
you are trying to solve in the first place. Once the problem domain is well understood, you are more apt to make
informed decisions about the design, which leads to better outcomes, faster.
behaviors are predictable. This provided convenience not only helps you hit the ground running in the right direction
sooner but increases your focus on the application domain so that you can better understand the problem you are trying
to solve in the first place. Once the problem domain is well understood, you are more apt to make informed decisions
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
infrastructure for Spring applications in a loosely integrated way by using conventions (such as the classpath) that ultimately
help you keep your attention and focus on solving the problem at hand and not on the plumbing.
This is exactly what Spring Boot's auto-configuration provides for you. It enables features, functionality, services
and supporting infrastructure for Spring applications in a loosely integrated way by using conventions (such as the
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`
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
container on startup (Boot's responsibility).
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 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
when you are trying to solve problems. You need not care how the plumbing works until you need to customize something. And, when you
do, you are better informed and prepared to do so.
This saves you from having to handle many low-level, repetitive, and tedious development tasks that are error-prone and
easy to get wrong when you are trying to solve problems. You need not care how the plumbing works until you need to
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
diverge from the provided defaults. The is the beautiful and powerful thing about Spring Boot and why it is second
to none in its class.
It is also equally essential that frameworks, such as Spring Boot, get out of the way quickly when application
requirements diverge from the provided defaults. This is the beautiful and powerful thing about Spring Boot and why
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
configuration in some cases, whether expressed as bean definitions, in properties, or by some other means. This is so that
frameworks do not leave things to chance, especially when they are ambiguous. The framework gives you a choice.
configuration in some cases, whether expressed as bean definitions, in properties, or by some other means. This is so
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:
* Refers you to the SDG annotations 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
* 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
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
{spring-session-data-gemfire-website}[Spring Session for {geode-name}]. SBDG refers to
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.
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.
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.
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`
* `@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)`
* `@EnableGatewayReceiver`
@@ -107,12 +109,12 @@ instance.
Other annotations are driven by need, including:
* `@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`
config to begin with. Otherwise, you should not do this.
formats, such as Spring config with {geode-name} `cache.xml`. This is usually the case only if you have legacy
`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.
* `@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
(that is, objects stored in {geode-name}) are generally uniform in size.
* `@EnableOffHeap`: Enables data to be stored in main memory, which is useful only when your application data (that is,
objects stored in {geode-name}) are generally uniform in size.
* `@EnableGemFireAsLastResource`: Needed only in the context of JTA Transactions.
* `@EnableStatistics`: Useful if you need runtime metrics. However, enabling statistics gathering does consume
considerable system resources (CPU & Memory).
@@ -123,20 +125,20 @@ Still other annotations require more careful planning:
* `@EnableExpiration`
* `@EnableIndexing`
One annotation is used exclusively for Unit Testing:
One annotation is used exclusively for unit testing:
* `@EnableGemFireMockObjects`
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).
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]]
=== Productivity Annotations
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]]
==== `@EnableClusterAware` (SBDG)
@@ -153,33 +155,35 @@ class SpringBootApacheGeodeClientCacheApplication { }
----
====
When you annotate your main `@SpringBootApplication` class with `@EnableClusterAware`,
your Spring Boot, {geode-name} `ClientCache` application is able to seamlessly switch between client/server
and local-only topologies with no code or configuration changes, regardless of the runtime environment
(such as local/standalone versus cloud-managed environments).
When you annotate your main `@SpringBootApplication` class with `@EnableClusterAware`, your Spring Boot, {geode-name}
`ClientCache` application is able to seamlessly switch between client/server and local-only topologies with no code
or configuration changes, regardless of the runtime environment (such as local/standalone versus cloud-managed
environments).
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
by using `LOCAL` Regions.
{geode-name} cluster. If a cluster is not available, the client automatically switches to storing data locally on the
client by using `LOCAL` Regions.
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
definitions, as needed by the application based on requirements and use cases) be sent to the cluster of servers.
If those schema objects are not already present, they are created by the servers in the cluster in such a way that
the servers remember the configuration on restart as well as provide the configuration to new servers that join
the cluster when it scales out. This feature is careful not to stomp on any existing region or index objects already
present on the servers, particularly since you may already have data stored in the regions.
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. If
those schema objects are not already present, they are created by the servers in the cluster in such a way that the
servers remember the configuration on restart as well as provide the configuration to new servers that join the cluster
when it is scaled out. This feature is careful not to stomp on any existing Region or Index objects already defined on
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
effort. It is a common development practice to debug and test your application locally (in your IDE) and
then push up to a production-like environment for more rigorous integration testing.
The primary motivation for the `@EnableClusterAware` annotation is to let you switch environments with minimal effort.
It is a common development practice to debug and test your application locally (in your IDE) and then push up to a
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
HTTPS, change the host and port, and configure the data management policy used by the servers when creating regions.
By default, the configuration metadata is sent to the cluster by using a non-secure HTTP connection. However, you can
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]
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.
`strictMatch` is set to `false` by default.
Essentially, when you set `strictMatch` to `true`, your Spring Boot, {geode-name} `ClientCache`
application requires an {geode-name} cluster to exist. That is, the application requires a client/server topology
to operate, and the application should fail to start if a cluster is not present. The application
should not startup in a local-only capacity.
Essentially, when you set `strictMatch` to `true`, your Spring Boot, {geode-name} `ClientCache` application requires
an {geode-name} cluster to exist. That is, the application requires a client/server topology to operate, and the
application should fail to start if a cluster is not present. The application should not startup in a local-only
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
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
====
@@ -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
to `INFO`, you get more details from the `@EnableClusterAware` functionality when applying the logic
to determine the presence of an {geode-name} cluster, such as which explicitly or implicitly configured connections
were successful.
to `INFO`, you get more details from the `@EnableClusterAware` functionality when applying the logic to determine
the presence of an {geode-name} cluster, such as which explicitly or implicitly configured connections were successful.
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`,
and the default `CacheServer` port, `40404`.
NOTE: An attempt is always made to connect to `localhost` on the default `Locator` port, `10334`, and the default
`CacheServer` port, `40404`.
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.
@@ -252,9 +256,9 @@ to `true` in Spring Boot `application.properties`. This is sometimes useful for
[[geode-configuration-declarative-annotations-productivity-regions]]
==== `@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
====
@@ -263,16 +267,17 @@ You can create regions by using Java configuration and the Spring API as follows
@Configuration
class GeodeConfiguration {
@Bean("Customers")
ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) {
@Bean("Customers")
ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) {
ClientRegionFactoryBean<Long, Customer> customers = new ClientRegionFactoryBean<>();
ClientRegionFactoryBean<Long, Customer> customers =
new ClientRegionFactoryBean<>();
customers.setCache(cache);
customers.setShortcut(ClientRegionShortcut.PROXY);
customers.setCache(cache);
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
configuration may be unknown and you want only to create a region to persist your application data and move on.
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.
[[geode-configuration-declarative-annotations-productivity-regions-enablecachingdefined]]
===== `@EnableCachingDefinedRegions`
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:
@@ -307,15 +314,16 @@ Consider the following example:
@Service
class CustomerService {
@Cacheable(cacheNames = "CustomersByAccountNumber", key = "#account.number")
Customer findBy(Account account) {
// ...
}
@Cacheable(cacheNames = "CustomersByAccountNumber", key = "#account.number")
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`
====
@@ -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
cluster) with a name of `CustomersByAccountNumber`, as though you created the region by using either the Java configuration or XML
approaches shown earlier.
With this setup, SBDG would create a client `PROXY` Region (or `PARTITION_REGION` if your application were a peer member
of the {geode-name} cluster) with a name of "`CustomersByAccountNumber`", as though you created the Region by using
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
regions created on the client or servers, respectively.
You can use the `clientRegionShortcut` or `serverRegionShortcut` attribute to change the data management policy of
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
to be used by the client `*PROXY` regions to send data to the cluster.
For client Regions, you can also set the `poolName` attribute to assign a specific `Pool` of connections to be used by
the client `*PROXY` Regions to send data to the cluster.
[[geode-configuration-declarative-annotations-productivity-regions-enableentitydefined]]
===== `@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.
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`
====
@@ -353,19 +362,19 @@ For instance, consider an entity class annotated with SDG's
@Region("Customers")
class Customer {
@Id
private Long id;
@Id
private Long id;
@Indexed
private String name;
@Indexed
private String name;
}
----
====
For this class, SBDG creates regions from the name specified in the `@Region` mapping annotation on the entity class. In this
case, the `Customer` application-defined entity class results in the creation of a region named `Customers` when
the main `@SpringBootApplication` class is annotated with `@EnableEntityDefinedRegions`:
For this class, SBDG creates Regions from the name specified in the `@Region` mapping annotation on the entity class.
In this case, the `Customer` application-defined entity class results in the creation of a Region named "`Customers`"
when the main `@SpringBootApplication` class is annotated with `@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
by using the `clientRegionShortcut` and `serverRegionShortcut` attributes, respectively, and set a dedicated pool
of connections used by client regions with the `poolName` attribute.
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`
of connections used by client Regions with the `poolName` 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`
annotation.
or the type-safe `basePackageClasses` attribute (recommended) when you use the `@EnableEntityDefinedRegions` annotation.
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.
@@ -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
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
sub-packages are scanned to determine if the class type represents an entity. A class type is an entity if it
is annotated with the `@Region` mapping annotation. Otherwise, it is not considered to be an entity.
sub-packages are scanned to determine if the class type represents an entity. A class type is an entity if it is
annotated with the `@Region` mapping annotation. Otherwise, it is not considered to be an entity.
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`,
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.
Additionally, the `@EnableEntityDefinedRegions` annotation provides include and exclude filters, the same as
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.
[[geode-configuration-declarative-annotations-productivity-regions-enableclusterdefined]]
===== `@EnableClusterDefinedRegions`
Sometimes, it is ideal or even necessary to pull configuration from the cluster (rather than push to the cluster).
That is, you want the regions defined on the servers to be created on the client and used by your application.
Sometimes, it is ideal or even necessary to pull configuration from the cluster (rather than push configuration to the
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`:
@@ -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
client as a bean in your Spring Boot application.
Every Region that exists on the servers in the {geode-name} cluster will have a corresponding `PROXY` Region defined
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
with the same name (`ServerRegion`) into your Spring Boot application:
If the cluster of servers defines a Region called "`ServerRegion`", you can inject a client `PROXY` Region with
the same name ("`ServerRegion`") into your Spring Boot application:
.Using a server-side Region on the client
====
@@ -472,23 +481,24 @@ with the same name (`ServerRegion`) into your Spring Boot application:
@Component
class SomeApplicationComponent {
@Resource(name = "ServerRegion")
private Region<Integer, EntityType> serverRegion;
@Resource(name = "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,>>),
so a better way to interact with the client `PROXY` region that corresponds to the `ServerRegion` region on the server
SBDG auto-configures a `GemfireTemplate` for the "`ServerRegion`" Region
(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:
.Using a server-side Region on the client with a template
@@ -498,43 +508,46 @@ is to inject the template:
@Component
class SomeApplicationComponent {
@Autowired
@Qualifier("serverRegionTemplate")
private GemfireTemplate serverRegionTemplate;
@Autowired
@Qualifier("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.
[[geode-configuration-declarative-annotations-productivity-enableindexing]]
==== `@EnableIndexing` (SDG)
You can also use the `@EnableIndexing` annotation -- but only when you use `@EnableEntityDefinedRegions`. This is because
`@EnableIndexing` requires the entities to be scanned and analyzed for mapping metadata (defined on the class type
of the entity). This includes annotations such as the Spring Data Commons `@Id` annotation a the annotations provided by SDG:
`@Indexed` and `@LuceneIndexed`.
You can also use the `@EnableIndexing` annotation -- but only when you use `@EnableEntityDefinedRegions`. This is
because `@EnableIndexing` requires the entities to be scanned and analyzed for mapping metadata (defined on the class
type of the entity). This includes annotations such as the Spring Data Commons `@Id` annotation and the annotations
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,
which are used in the predicates of your OQL Queries. The `@LuceneIndexed` annotation is used to define the Apache Lucene
indexes required for searches.
The `@Id` annotation identifies the (primary) key of the entity. The `@Indexed` annotation defines OQL indexes on object
fields, which can be used in the predicates of your OQL queries. The `@LuceneIndexed` annotation is used to define the
Apache Lucene Indexes required for searches.
NOTE: Lucene Indexes can only be created on `PARTITION` regions, and `PARTITION` regions are only defined
on the server side.
NOTE: Lucene Indexes can only be created on `PARTITION` Regions, and `PARTITION` Regions can only be defined on
the server side.
You may have noticed that the `Customer` entity class's `name` field was annotated with `@Indexed`.
Consider the following listing:
Consider the following listing:
.Customer entity class with `@Indexed` annotated `name` field
====
[source,java]
@@ -542,19 +555,18 @@ Consider the following listing:
@Region("Customers")
class Customer {
@Id
private Long id;
@Id
private Long id;
@Indexed
private String name;
@Indexed
private String name;
}
----
====
As a result, when our main `@SpringBootApplication` class is annotated with `@EnableIndexing`,
an {geode-name} OQL index for the `Customer.name` field is created, making OQL Queries on customers by name
use this index:
As a result, when our main `@SpringBootApplication` class is annotated with `@EnableIndexing`, an {geode-name} OQL Index
for the `Customer.name` field is created, allowing OQL queries on customers by name to use this Index:
.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
only). An OQL Index is always rebuilt when the node is restarted.
NOTE: Keep in mind that OQL Indexes are not persistent between restarts (that is, {geode-name} maintains Indexes
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
definitions are pushed to the server-side regions where OQL Queries are generally executed.
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.
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.
[[geode-configuration-declarative-annotations-productivity-enableexpiration]]
==== `@EnableExpiration` (SDG)
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
exceed the amount of available JVM heap memory, and keeping too much data on the JVM Heap can cause Garbage Collection
(GC) issues.
because it primarily keeps data in memory (on the JVM Heap). Your data volume size may far exceed the amount of
available JVM Heap memory, and keeping too much data on the JVM Heap can cause Garbage Collection (GC) issues.
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.
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
SDG, we particularly want to call out expiration since
{spring-data-geode-docs-html}/#bootstrap-annotation-config-region-expiration[configuring expiration] has special
support in SDG.
While {spring-data-geode-docs-html}/#bootstrap-annotation-config-region-eviction[configuring eviction] is easy with SDG,
we particularly want to call out expiration since
{spring-data-geode-docs-html}/#bootstrap-annotation-config-region-expiration[configuring expiration] has special support
in SDG.
With SDG, you can define the expiration policies associated with a particular application class type on the
class type 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`],
With SDG, you can define the expiration policies associated with a particular application class type on the class type
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`]
and {spring-data-geode-javadoc}/org/springframework/data/gemfire/expiration/TimeToLiveExpiration.html[`@TimeToLiveExpiration`]
annotations.
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
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
policy on our `Customer` class type:
seconds) based on the last time a `Customer` was accessed (for example, the last time a `Customer` was read). To do so,
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]
----
@@ -616,11 +629,11 @@ policy on our `Customer` class type:
@IdleTimeoutExpiration(action = "INVALIDATE", timeout = "300")
class Customer {
@Id
private Long id;
@Id
private Long id;
@Indexed
private String name;
@Indexed
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
{apache-geode-javadoc}/org/apache/geode/cache/CustomExpiry.html[`CustomExpiry`] interface.
TIP: See the SDG Reference Guide for more details on
{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.
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:region:expiration:annotation[annotation-based data expiration] in particular.
[[geode-configuration-declarative-annotations-productivity-enablemockobjects]]
==== `@EnableGemFireMockObjects` (STDG)
Software testing in general and unit testing in particular are a very important development tasks to ensure
the quality of your Spring Boot applications.
Software testing in general and unit testing in particular are a very important development tasks to ensure the quality
of your Spring Boot applications.
{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
can write unit tests as well.
to assert the correct behavior. This can be very costly and lengthens the feedback cycle. Fortunately, you can write
unit tests as well.
Spring provides a framework for testing Spring Boot applications that use {geode-name}. This
is where the {spring-test-data-gemfire-website}[Spring Test for {geode-name} (STDG)] project can help, particularly with
Spring provides a framework for testing Spring Boot applications that use {geode-name}. This is where the
{spring-test-data-gemfire-website}[Spring Test for {geode-name} (STDG)] project can help, particularly with
unit testing.
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
isolate the "`Subject Under Test`" (SUT) and focus on the interactions or outcomes you expect to happen.
which is what mocking a collaborator is all about, you could effectively mock {geode-name} objects to isolate the SUT,
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`:
.Using Mock {geode-name} Objects
@@ -677,20 +690,20 @@ applications. You need only annotate the test class with `@EnableGemFireMockObje
@SpringBootTest
class MyApplicationTestClass {
@Test
public void someTestCase() {
// ...
}
@Test
public void someTestCase() {
// ...
}
@Configuration
@EnableGemFireMockObjects
static class GeodeConfiguration { }
@Configuration
@EnableGemFireMockObjects
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
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`
annotation would be a "`mock`" region and not an actual region. You can still inject the region in your test
and assert interactions on the region based on your application workflows:
In the preceding example, the `"Customers`" Region defined by the `Customer` entity class and created by
the `@EnableEntityDefinedRegions` annotation would be a mock Region and not an actual Region. You can still inject
the Region in your test and assert interactions on the Region based on your application workflows:
.Using Mock {geode-name} Objects
====
@@ -719,30 +732,30 @@ and assert interactions on the region based on your application workflows:
@SpringBootTest
class MyApplicationTestClass {
@Resource(name = "Customers")
private Region<Long, Customer> customers;
@Resource(name = "Customers")
private Region<Long, Customer> customers;
@Test
public void someTestCase() {
@Test
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.
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.
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
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.

View File

@@ -3,13 +3,13 @@
: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
for {geode-name} (SBDG) supports externalized configuration.
Like Spring Boot itself (see {spring-boot-docs-html}/boot-features-external-config.html[Spring Boot's documentation]),
Spring Boot for {geode-name} (SBDG) supports externalized configuration.
By externalized configuration, we mean configuration metadata stored in a Spring Boot
{spring-boot-docs-html}/boot-features-external-config.html#boot-features-external-config-application-property-files[`application.properties` file],
for instance. 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].
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`].
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].
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]
@@ -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
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}
====
@@ -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,
{geode-name} applications. See the
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-frame.html[Javadoc]
You can use many other properties to externalize the configuration of your Spring Boot, {geode-name} applications.
See the {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-frame.html[Javadoc]
for specific configuration properties. Specifically, review the `enabling` annotation attributes.
You may sometimes require access to the configuration metadata (specified in properties)
in your Spring Boot applications themselves, perhaps to further inspect or act on a particular configuration setting.
You can access any property by using Spring's {spring-framework-javadoc}/org/springframework/core/env/Environment.html[`Environment`] abstraction:
You may sometimes require access to the configuration metadata (specified in properties) in your Spring Boot
applications themselves, perhaps to further inspect or act on a particular configuration setting. You can access any
property by using Spring's {spring-framework-javadoc}/org/springframework/core/env/Environment.html[`Environment`]
abstraction:
.Using the Spring `Environment`
====
@@ -62,16 +62,18 @@ You can access any property by using Spring's {spring-framework-javadoc}/org/spr
----
@Configuration
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
the property values in a type-safe manner. Therefore, you can now, thanks to SBDG's auto-configured
configuration processor, access the configuration metadata by using `@ConfigurationProperties` classes.
the property values in a type-safe manner. Therefore, you can now, thanks to SBDG's auto-configured configuration
processor, access the configuration metadata by using `@ConfigurationProperties` classes.
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]
----
@Component
class MyApplicationComponent {
@Autowired
private GemFireProperties gemfireProperties;
@Autowired
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`],
you can access any of the configuration properties that are used to configure {geode-name} in a Spring context. You need only
autowire an instance of `GemFireProperties` into your application component.
you can access any of the configuration properties that are used to configure {geode-name} in a Spring context. You need
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]]
=== Externalized Configuration of Spring Session
You can access the externalized configuration of Spring Session when you use {geode-name} as
your (HTTP) Session state caching provider.
You can access the externalized configuration of Spring Session when you use {geode-name} as your (HTTP) session state
caching provider.
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`]
@@ -114,11 +116,12 @@ class.
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]
----
# 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.region.name=UserSessions
@@ -134,15 +137,16 @@ Then, in your application, you can do something similar to the following example
@Component
class MyApplicationComponent {
@Autowired
private SpringSessionProperties springSessionProperties;
@Autowired
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
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
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}.
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).
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]]
=== 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`
property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `application.properties`.
.`spring.data.gemfire.*` properties
[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
[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.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.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-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.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-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.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.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.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
[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
[width="90%",options="header"]
|=====================================================================================================================
| 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-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`]
@@ -75,7 +74,6 @@ property, use `spring.data.gemfire.cache.copy-on-read` in Spring Boot `applicati
|=====================================================================================================================
.`spring.data.gemfire.*` _CacheServer_ properties
[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
of the `CacheServer` bean defined in the Spring application context. Consider the following example:
`CacheServer` properties can be further targeted at specific `CacheServer` instances by using an optional bean name
of the `CacheServer` bean defined in the Spring `ApplicationContext`. Consider the following example:
====
[source,properties]
@@ -109,23 +107,21 @@ spring.data.gemfire.cache.server.[<cacheServerBeanName>].bind-address=...
----
====
.`spring.data.gemfire.*` Cluster properties
[width="90%",options="header"]
|=====================================================================================================================
| 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
[width="90%",options="header"]
|=====================================================================================================================
| 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.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`]
@@ -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,
the properties apply to all `DiskStore` instances. Without array indexes, all named `DiskStore` files are stored in the
specified location and limited to the defined size.
the properties apply to all `DiskStore` instances. Without array indexes, all named `DiskStore` files are stored in
the specified location and limited to the defined size.
.`spring.data.gemfire.*` Entity properties
[width="90%",options="header"]
@@ -182,12 +178,11 @@ specified location and limited to the defined size.
|=====================================================================================================================
| 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`]
|=====================================================================================================================
.`spring.data.gemfire.*` Logging properties
[width="90%",options="header"]
|=====================================================================================================================
@@ -200,35 +195,32 @@ specified location and limited to the defined size.
|=====================================================================================================================
.`spring.data.gemfire.*` Management properties
[width="90%",options="header"]
|=====================================================================================================================
| 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.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.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.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} Manager that runs the HTTP service. | | {spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableClusterConfiguration.html#host--[`EnableClusterConfiguration.host`]
| `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"]
|=====================================================================================================================
| 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.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.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.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.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.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.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
[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.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.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`]
|=====================================================================================================================
.`spring.data.gemfire.*` Pool properties
[width="90%",options="header"]
|=====================================================================================================================
| 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.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.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.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.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.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.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.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.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.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-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.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`]
|=====================================================================================================================
.`spring.data.gemfire.*` Security properties
[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-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.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.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.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.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.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
[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.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.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.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`]
@@ -324,7 +313,6 @@ specified location and limited to the defined size.
|=====================================================================================================================
.`spring.data.gemfire.*` Service properties
[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.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.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.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.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.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.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]]
=== Spring Session Based Properties
The following properties all have a `spring.session.data.gemfire.*` prefix. For example, to set the session region
name, set `spring.session.data.gemfire.session.region.name` in Spring Boot `application.properties`.
The following properties all have a `spring.session.data.gemfire.*` prefix. For example, to set the session Region name,
set `spring.session.data.gemfire.session.region.name` in Spring Boot `application.properties`.
.`spring.session.data.gemfire.*` properties
[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
| `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.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`]
| `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`]
| `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.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`]
|=====================================================================================================================
@@ -367,8 +354,8 @@ name, set `spring.session.data.gemfire.session.region.name` in Spring Boot `appl
[[geode-configuration-metadata-apachegeode]]
=== {geode-name} Properties
While we do not recommend using {geode-name} properties directly in your Spring applications, SBDG does not prevent
you from doing so. See the {apache-geode-docs}/reference/topics/gemfire_properties.html[complete reference to the {geode-name} specific properties].
While we do not recommend using {geode-name} properties directly in your Spring applications, SBDG does not prevent you
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
cannot mix Spring properties with `gemfire.*` properties in an {geode-name} `gemfire.properties` file.
WARNING: {geode-name} is very strict about the properties that may be specified in a `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
: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
need frameworks that can make processing a stream of events as they happen as easy as possible.
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 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
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
easily define your criteria for the data you need. With CQ, you can
express the criteria that match the data you need by using a query predicate. {geode-name} implements
the {apache-geode-docs}/developing/querying_basics/query_basics.html[Object Query Language (OQL)] for defining
and executing queries. OQL resembles SQL and supports projections, query predicates, ordering, and aggregates.
Also, when used in CQs, they execute continuously, firing events when the data changes in such ways as to match
the criteria expressed in the query predicate.
easily define your criteria for the data you need. With CQ, you can express the criteria that match the data you need
by specifying a query predicate. {geode-name} implements the
{apache-geode-docs}/developing/querying_basics/query_basics.html[Object Query Language (OQL)]
for defining and executing queries. OQL resembles SQL and supports projections, query predicates, ordering,
and aggregates. Also, when used in CQs, they execute continuously, firing events when the data changes in such ways
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
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
is either approved or denied.
For example, suppose you want to perform some follow-up action when a customer's financial loan application is either
approved or denied.
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
is either `APPROVED` or `DENIED`:
Then we can implement and declare our CQ event handler methods to be notified when an eligibility decision is either
`APPROVED` or `DENIED`:
====
[source,java]
@@ -59,7 +60,6 @@ is either `APPROVED` or `DENIED`:
@Component
class EligibilityDecisionPostProcessor {
@ContinuousQuery(name = "ApprovedDecisionsHandler",
query = "SELECT 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
gets notified, and as an application developer, you are free to code your handler and respond to the event
any way you like. Also, because our continuous query handler class is a component (or a bean in the Spring
`ApplicationContext`) you can auto-wire any other beans necessary to carry out the application's intended function.
Thus, when eligibility is processed and a decision has been made, either approved or denied, our application gets
notified, and as an application developer, you are free to code your handler and respond to the event any way you like.
Also, because our Continuous Query (CQ) handler class is a component (or a bean in the Spring `ApplicationContext`)
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],
which are used in (JMS) message listeners and handlers, except in Spring Boot for {geode-name}, you need not do anything special
to enable this functionality. You can declare the `@ContinuousQuery` annotation on any POJO method go work on other things.
which are used in (JMS) message listeners and handlers, except in Spring Boot for {geode-name}, you need not do anything
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
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
a large number of application domain object types that currently do not implement `java.io.Serializable`,
refactoring hundreds or even thousands of class types to implement `Serializable` would be a tedious task just to
store and manage those objects in {geode-name}.
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 WAN topology, all data stored in {geode-name} must be
serializable.
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 be serializable too. This type explosion may bleed into class types for which you may have
To serialize objects in Java, object types must implement the `java.io.Serializable` interface. However, if you have a
large number of application domain object types that currently do not implement `java.io.Serializable`, refactoring
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.
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.
Then, along came serialization using {geode-name}'s {apache-geode-docs}/developing/data_serialization/gemfire_pdx_serialization.html[PDX]
format. PDX stands for Portable Data Exchange and achieves four goals:
Then, along came serialization using {geode-name}'s
{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
a type registry that stores type metadata about the objects serialized in PDX.
* Separates type metadata from the data itself, streamlining the bytes during transfer. {geode-name} maintains a type
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
deployed to production, running simultaneously, sharing data, and possibly using different versions of the same domain
types. PDX lets fields be added or removed while still preserving interoperability between old and new application
clients without loss of data.
* Supports versioning as your application domain types evolve. It is common to have old and new versions of the same
application deployed to production, running simultaneously, sharing data, and possibly using different versions of the
same domain types. PDX lets fields be added or removed while still preserving interoperability between old and new
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
is a resource-intensive task that adds to the latency of each data request when redundancy is enabled. Since data must be
replicated across peers in the cluster to preserve High Availability (HA) and must be serialized to be transferred, keeping
data serialized is more efficient when data is updated frequently, since it likely needs to be transferred again
to maintain consistency in the face of redundancy and availability.
* Enables objects stored as PDX to be queried without being de-serialized. Constant serialization and deserialization of
data is a resource-intensive task that adds to the latency of each data request when redundancy is enabled. Since data
is replicated across peers in the cluster to preserve High Availability (HA) and must be serialized to be transferred,
keeping data serialized is more efficient when data is updated frequently, since it is likely the data will need to be
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.
However, PDX does have limitations.
For instance, unlike Java serialization, PDX does not handle cyclic dependencies. Therefore, you must be careful
how you structure and design your application domain object types.
For instance, unlike Java serialization, PDX does not handle cyclic dependencies. Therefore, you must be careful how you
structure and design your application domain object types.
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]
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:
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
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.
However, we think the benefits of using PDX greatly outweigh the limitations and, therefore, have enabled PDX by default
when using Spring Boot for {geode-name}.
However, we think the benefits of using PDX outweigh the limitations and, therefore, have enabled PDX by default.
You need do nothing special. You can code your types and rest assured that objects of those types are
properly serialized when overflowed and persisted to disk, transferred between clients and servers, transferred between peers in a cluster,
and even when data is transferred over the WAN when you use {geode-name}'s multi-site topology.
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, 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.
====
@@ -74,44 +79,47 @@ Java Serialization format.
=== 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]
and uses Spring Data for {geode-name}'s {spring-data-geode-javadoc}/org/springframework/data/gemfire/mapping/MappingPdxSerializer.html[`MappingPdxSerializer`]
to serialize your application domain objects by using PDX.
and uses Spring Data for {geode-name}'s
{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
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.
TIP: See {geode-name}'s {apache-geode-docs}/developing/data_serialization/auto_serialization.html[User Guide]
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
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`
and `com.gemstone.gemfire`.
* Handles {spring-data-geode-docs-html}/#mapping.pdx-serializer.transient-properties[transient object fields 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.transient-properties[transient object fields
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].
* 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.
* Lets `o.a.g.pdx.PdxSerializers` be registered to {spring-data-geode-docs-html}/#mapping.pdx-serializer.custom-serialization[customize the serialization]
of nested entity field and property types.
* Lets additional `o.a.g.pdx.PdxSerializers` be registered to
{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}
types, by default. However,, what happens when you need to serialize one of those types?
The support for `includes` and `excludes` deserves special attention, since the `MappingPdxSerializer` excludes all Java,
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
override the excludes by registering an "`include`" type filter:
For example, suppose you need to serialize objects of type `java.security.Principal`. Then you can override the excludes
by registering an `include` type filter:
====
[source,java]
@@ -143,5 +151,5 @@ class SpringBootApacheGeodeClientCacheApplication {
----
====
TIP: Normally, you need not explicitly declare SDG's `@EnablePdx` annotation to enable and configure PDX.
However, if you want to override auto-configuration, as we have demonstrated above, you must do this.
TIP: Normally, you need not explicitly declare SDG's `@EnablePdx` annotation to enable and configure PDX. However,
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.
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.
{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}/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.
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
data while it is being imported and exported.
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 data
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].
TIP: Spring Data for {geode-name} (SDG) contains dedicated support for {spring-data-geode-docs-html}/#bootstrap:region:persistence[persistence]
and the {spring-data-geode-docs-html}/#bootstrap:snapshot[snapshot service].
TIP: Spring Data for {geode-name} (SDG) contains dedicated support for
{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
proprietary binary format.
In all cases, the files generated by persistence, the Snapshot Service and Gfsh's `export` command are in a proprietary
binary format.
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.
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
(the `Region` instances) that manage your data is with SDG's annotation-based configuration support for defining cache `Region` instances
from your application's {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[entity classes] or indirectly
from Spring and JSR-107 or JCache {spring-data-geode-docs-html}/#bootstrap-annotation-config-caching[caching annotations].
(the `Region` instances) that manage your data is with SDG's annotation-based configuration support for defining cache
`Region` instances from your application's {spring-data-geode-docs-html}/#bootstrap-annotation-config-regions[entity classes]
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.
WARNING: While this feature works and many edge cases were thought through and tested thoroughly, there are still
some limitations that need to be ironed out. See https://github.com/spring-projects/spring-boot-data-geode/issues/82[issue-82]
WARNING: While this feature works and many edge cases were thought through and tested thoroughly, there are still some
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
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
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`
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()`].
For example, if you have a `Region` named `Orders`, you would create a JSON file called `data-orders.json`
and place it in the root of your application classpath (for example, in `src/test/resources`).
For example, if you have a `Region` named "Orders", you would create a JSON file called `data-orders.json` and place it
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
defined (with `ClientRegionFactoryBean` in Java configuration) in your Spring Boot application configuration that you
want to load with data.
Create JSON files for each `Region` that is implicitly defined (for example, by using `@EnableEntityDefinedRegions`)
or explicitly defined (with `ClientRegionFactoryBean` in Java configuration) in your Spring Boot application
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`
====
@@ -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]
----
@@ -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
that have complex types.
As the preceding listings show, the object model and corresponding JSON can be arbitrarily complex with a hierarchy of
objects that have complex types.
[[geode-data-using-import-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]]
===== 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,
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()`]
does not refer to a valid Java class. It is {apache-geode-javadoc}/org/apache/geode/pdx/JSONFormatter.html#JSON_CLASSNAME[`JSONFormatter.JSON_CLASSNAME`].
NOTE: When JSON is imported into a `Region` as PDX, the
{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.
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
wrap a `PdxInstance` in a `PdxInstanceWrapper` to appropriately handle the `PdxInstance.getObject()` call in
your application code.
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 wrap a `PdxInstance` in a `PdxInstanceWrapper` to appropriately handle the `PdxInstance.getObject()` call
in your application code.
[[geode-data-using-import-metadata-id]]
===== 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
identity and "`key`" of the object (or `PdxInstance`) when stored in the `Region` (for example, `Region.put(key, object)`).
Top-level objects in your JSON must have an identifier, such as an `id` field. This identifier is used as the identity
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")
====
@@ -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 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`.
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:
@@ -265,8 +273,8 @@ format. There might not be a class definition, which would lead to a `NoClassDef
So, what then?
In this case, SBDG lets you declare the `@identifier` JSON metadata field to inform the framework
what to use as the identifier for the object.
In this case, SBDG lets you declare the `@identifier` JSON metadata field to inform the framework what to use as
the identifier for the object.
Consider the following example:
@@ -294,18 +302,18 @@ The `@identifier` JSON metadata field informs the framework that the `isbn` fiel
==== Conditionally Importing Data
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
largely static, infrequently changing, and non-transactional. Preloading reference data is particularly useful
when you want to "`warm`" the cache.
You might use this feature in production to preload a (REPLICATE) Region with reference data. Reference data is largely
static, infrequently changing, and non-transactional. Preloading reference data is particularly useful when you want to
warm the cache.
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
deployed to production.
`src/test/resources`. This ensures that the files are not included in your application artifact (such as a JAR or WAR)
when built and deployed to production.
However, if you must use this feature to preload data in your production environment, you can still "`conditionally`"
load data from JSON. To do so, configure the `spring.boot.data.gemfire.cache.data.import.active-profiles` property set to
However, if you must use this feature to preload data in your production environment, you can still conditionally load
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.
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`
property to one of the valid, `active-profiles` listed in the import property (such as `QA`). Only one needs to match.
For import to have an effect in this example, you must specifically set the `spring.profiles.active` property to one of
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
in your Gradle or Maven build.
NOTE: There are many ways to conditionally build application artifacts. You might prefer to handle this concern in your
Gradle or Maven build.
[[geode-data-using-export]]
=== 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
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
useful to move data from one environment to another. For example, if your QA team finds a bug in the application that uses a
However, if you use this feature for development and testing purposes, enabling the export capability may be useful to
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
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
`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
an `@identifier` metadata field before it is exported to JSON if necessary (for example, `Book.isbn`). This is only necessary
if your entity classes do not declare an explicit identifier field, such as with the `@Id` mapping annotation, or do
not have an `id` field. This scenario can also occur when inter-operating with native clients that model the application
domain objects differently and then serialize the objects by using PDX and storing them in regions on the server that are then
later consumed by your Spring Boot application.
is a `PdxInstance` that did not originate from JSON. In this case, you must manually ensure that the `PdxInstance`
includes an `@identifier` metadata field before it is exported to JSON if necessary (for example, `Book.isbn`). This is
only necessary if your entity classes do not declare an explicit identifier field, such as with the `@Id` mapping
annotation, or do not have an `id` field. This scenario can also occur when inter-operating with native clients
that model the application domain objects differently and then serialize the objects by using PDX, storing them in
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
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
can "`export the data`", thereby resulting in a `CacheClosedException`. SBDG
in {geode-name} by default, which results in the cache and the Regions being closed before the SBDG Export
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]
to disable the {geode-name} shutdown hook when export is enabled, but it is at the mercy of the JVM `ClassLoader`, since
{geode-name}'s JVM shutdown hook
to disable the {geode-name} JVM shutdown hook when export is enabled, but it is at the mercy of the JVM `ClassLoader`,
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]
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 Writing
By breaking each of these functions apart into separate concerns, a developer can customize each
aspect of the import and export functions.
By breaking each of these functions apart into separate concerns, a developer can customize each aspect of the import
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
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
control over each aspect of the import and export processes is essential for performing the functions in any environment.
However, not all environments expose a filesystem, such as cloud environments like PCF. Therefore, giving users control
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]]
==== 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
that implements the `CacheDataImporter` interface in the Spring container, and the importer does its job.
You can code the `importInto(:Region)` method to handle any data format (JSON, XML, and others) you prefer. Register a
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`.
@@ -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
implementing the `CacheDataExporter` interface in the Spring container, and the exporter does its job.
You can code the `exportFrom(:Region)` method to handle any data format (JSON, XML, and others) you prefer. Register a
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
`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.
[[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.
This is especially true on import, since different `Region` instances may be collocated or tied together through a cache callback, such as
`CacheListener`. In these cases, the other `Region` may need to exist before the import on the dependent `Region`
proceeds, particularly if the dependencies were loosely defined.
This is especially true on import, since different `Region` instances may be collocated or tied together through a
cache callback, such as a `CacheListener`. In these cases, the other `Region` may need to exist before the import
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
push configuration metadata from the client to the cluster in order to define server-side `Region` instances that match the
client-side `Region` instances, especially client `Region` instances targeted for import. The matching `Region` instances on the server side must
exist before data is imported into client (`PROXY`) `Region` instances.
Controlling the import is also important when you use SBDG's `@EnableClusterAware` annotation to push configuration
metadata from the client to the cluster in order to define server-side `Region` instances that match the client-side
`Region` instances, especially client `Region` instances targeted for import. The matching `Region` instances on the
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`
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.
By implementing the `SmartLifecycle` interface, you can control in which `phase` of the Spring container
the import occurs. SBDG also exposes two more properties to control the lifecycle:
By implementing the `SmartLifecycle` interface, you can control in which `phase` of the Spring container the import
occurs. SBDG also exposes two more properties to control the lifecycle:
.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
`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]
@@ -534,9 +543,9 @@ interface ResourceResolver {
----
====
Additionally, SBDG provides the `ImportResourceResolver` and `ExportResourceResolver` marker interfaces and
the `AbstractImportResourceResolver` and `AbstractExportResourceResolver` abstract base classes for implementing
the resource resolution logic used by both import and export operations.
Additionally, SBDG provides the `ImportResourceResolver` and `ExportResourceResolver` marker interfaces and the
`AbstractImportResourceResolver` and `AbstractExportResourceResolver` abstract base classes for implementing the
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`
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.
You can customize this behavior by providing an implementation of
`ImportResourceResolver`, `ExportResourceResolver`, or both interfaces and declare instances as beans in the Spring context:
You can customize this behavior by providing an implementation of `ImportResourceResolver`, `ExportResourceResolver`,
or both interfaces and declare instances as beans in the Spring context:
.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
can use the https://en.wikipedia.org/wiki/Composite_pattern[composite software design pattern].
TIP: If you need to customize the resource resolution process for each location (or `Region`) on import or export,
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]]
===== 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
{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).
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 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]
@@ -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),
directly from the `Environment` by using map style syntax as follows:
You can access more complex property names (including properties that use dot notation, such as the `user.home`
Java System property), directly from the `Environment` by using map style syntax as follows:
====
[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`.
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
`someBean.lookupPassword(..)`. `someBean` must be the name of the bean as declared or registered in the Spring context.
access to the beans declared and registered in the Spring container and can invoke methods on them, as shown earlier
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.
SBDG also sets the `#regionName` variable in the `EvaluationContext` to the name of the `Region`,
as determined by {apache-geode-javadoc}/https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/Region.html#getName--[`Region.getName()`],
targeted for import/export.
SBDG also sets the `#regionName` variable in the `EvaluationContext` to the name of the `Region`, as determined by
{apache-geode-javadoc}/https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/Region.html#getName--[`Region.getName()`],
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).
@@ -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
Spring Boot application process.
NOTE: By default, the exported file is stored in the working directory (`System.getProperty("user.dir")`)
of the Spring Boot application process.
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]]
==== Reading & Writing Resources
The Spring {spring-framework-javadoc}/org/springframework/core/io/Resource.html[`Resource`] handle specifies
the location of a resource, not how to read or write it. Even the Spring
{spring-framework-javadoc}/org/springframework/core/io/ResourceLoader.html[`ResourceLoader`], which is an interface for
"`loading`" `Resources`, does not specifically read or write any content to the `Resource`.
The Spring {spring-framework-javadoc}/org/springframework/core/io/Resource.html[`Resource`] handle
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 loading `Resources`, does not specifically read or write any content to the `Resource`.
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 `java.io` package.
The design follows the same pattern used by Java's `InputStream/OutputStream` and `Reader/Writer` classes
in the `java.io` package.
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`
and `Function` interfaces in the `java.util.function` package. If a particular reader or writer is used in a composition
and is unable to handle the given `Resource`, it should throw a `UnhandledResourceException` to let the next
reader or writer in the composition try to read from or write to the `Resource`.
Both interfaces provide additional methods to compose readers and writers, much like Java's `Consumer` and `Function`
interfaces in the `java.util.function` package. If a particular reader or writer is used in a composition and is unable
to handle the given `Resource`, it should throw a `UnhandledResourceException` to let the next reader or writer in the
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
chain of reader and writer invocations in the composition.
The reader or writer are free to throw a `ResourceReadException` or `ResourceWriteException` to break the chain of
reader and writer invocations in the composition.
To override the default export/import reader and writer used by SBDG, you can implement
the `ResourceReader` or `ResourceWriter` interfaces as appropriate and declare instances of these classes as beans
in the Spring context:
To override the default export/import reader and writer used by SBDG, you can implement the `ResourceReader`
or `ResourceWriter` interfaces as appropriate and declare instances of these classes as beans in the Spring container:
.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
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
model for creating, using, and managing containers to run packaged applications.
The state of modern software application development is moving towards https://www.docker.com/resources/what-container[containerization].
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]
and Spring Boot's now {spring-boot-docs-html}/spring-boot-features.html#building-docker-images[dedicated support]
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.
Understandably, {docker-site-url}[Docker's] popularity took off like wildfire, given its highly powerful and simplified
model for creating, using and managing containers to run packaged applications.
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.
{geode-name} can also run in a controlled, containerized environment. The goal of this chapter
is to get you started running {geode-name} in a container and interfacing to a containerized {geode-name} cluster from
your Spring Boot, {geode-name} client applications.
{geode-name} can also run in a controlled, containerized environment. The goal of this chapter is to get you started
running {geode-name} in a container and interfacing to a containerized {geode-name} cluster from your Spring Boot,
{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
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]
and {spring-boot-docs-html}/deployment.html#containers-deployment[container deployment], along with Docker's {docker-docs-url}/get-started/overview/[documentation]).
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]
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,
{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]]
=== 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}
Docker image from https://hub.docker.com/r/apachegeode/geode/[Docker Hub].
To run an {geode-name} cluster inside a Docker container, you must first acquire the Docker image. You can get
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,
we find a bit of relief in the {apache-geode-wiki}/How+to+use+Geode+on+Docker[Wiki]. However, for a complete and
comprehensive write up, see the instructions in the https://github.com/markito/geode-docker#building-the-container-image[README]
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 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].
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:
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
====
@@ -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
`latest` tag, which pulls a stable, production-ready {geode-name} Docker image based on the latest {geode-name}
Instead of pulling from the `nightly` tag as suggested, the Spring team highly recommends that you pull from
the `latest` tag, which pulls a stable, production-ready {geode-name} Docker image based on the latest {geode-name}
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]
@@ -83,8 +92,8 @@ Now you are ready to run {geode-name} in a Docker container.
[[geode-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
following `docker run` command to start {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 following `docker run` command to start {geode-name} in a 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
interactive shell.
You know that the {geode-name} Docker container is running since we ended up at a Gfsh command prompt in
the interactive shell.
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
[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
of provisioning a cluster. It would have been more useful to provide preconfigured Docker images with different
{geode-name} cluster configurations, such as one Locator and one server or two locators and four servers, and so on. However, we
can start the cluster ourselves.
It is unfortunate that the {geode-name} Docker image gives you only a Gfsh command prompt, leaving you with the task of
provisioning a cluster. It would have been more useful to provide preconfigured Docker images with different {geode-name}
cluster configurations, such as one Locator and one server or two Locators and four servers, and so on. However, we can
start the cluster ourselves.
[[geode-docker-cluster]]
=== 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
====
@@ -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
started the cluster with a minimal configuration. For example, we have no regions in which to store data:
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:
====
[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
====
@@ -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.
We additionally annotate the main class with SBDG's `@EnableClusterAware` to automatically detect the {geode-name}
cluster that runs in the Docker Container and to push cluster configuration metadata from the application to
the cluster as required by the application.
We additionally annotate the main class with SBDG's `@EnableClusterAware` annotation to automatically detect
the {geode-name} cluster that runs in the Docker container and to push cluster configuration metadata from
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
on the `Customer` application domain model class, exists on the servers in the cluster, to persist `Customer` data.
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 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`
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
essentially create a `Customer` instance (`Jon Doe`), save it to the `Customers` region that is managed by the server
in the cluster, and then query for `Jon Doe` using OQL, asserting that the result is equal to what we expect.
The primary work performed by this application is done in the Spring Boot `ApplicationRunner` bean definition. We create
a `Customer` instance (`Jon Doe`), save it to the "Customers" Region that is managed by the server in the cluster,
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.
@@ -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 the application ran:
When we review the configuration of the cluster, we see that the `/Customers` Region was created when the application
ran:
./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:
.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
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
Docker. Additionally, we provide details on how you can use {geode-name}'s Docker Image with Testcontainers
when you write integration tests, which formally became part of the Spring Test for {geode-name} (STDG) project.
Later, we provide more information on how to scale up, or rather scale out, our {geode-name} cluster that runs in Docker.
Additionally, we provide details on how you can use {geode-name}'s Docker image with Testcontainers when you write
integration tests, which formally became part of the Spring Test for {geode-name} (STDG) project.

View File

@@ -2,12 +2,13 @@
== Function Implementations & Executions
:geode-name: {apache-geode-name}
This chapter is about using {geode-name} in a Spring context for distributed computing use cases.
=== Background
Distributed processing, 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].
Distributed computing, particularly in conjunction with data access and mutation operations, is a very effective
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
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.
{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]
and {spring-data-geode-docs-html}/#function-execution[execute] {geode-name} functions with a simple POJO-based
annotation configuration model.
TIP: See {spring-data-geode-docs-html}/#_implementation_vs_execution[the section about implementation versus execution] for the difference between
function implementation and execution.
TIP: See {spring-data-geode-docs-html}/#_implementation_vs_execution[the section about implementation versus 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
and execution out-of-the-box. Therefore, you can immediately begin writing functions and invoking them without having
to worry about all the necessary plumbing to begin with. You can rest assured that it works as expected.
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 to
worry about all the necessary plumbing to begin with. You can rest assured that it works as expected.
=== 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.
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
in order to not have to recompute or redetermine eligibility every time a loan office may want to review the decision
with the customer.
history, gathering information on outstanding loans, and so on. We applied caching in order to not have to recompute
or redetermine eligibility every time a loan office may want to review the decision 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
the eligibility determination in place. However, it might be far better to distribute the processing and even
determine eligibility for a larger group of people all at once, especially when multiple, related people are involved
in a single decision, as is typically the case.
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 determine
eligibility for a larger group of people all at once, especially when multiple, related people are involved in a single
decision, as is typically the case.
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`]
annotation, we can implement our function as a POJO method. SDG appropriately handles registering this POJO method
as a proper function with {geode-name}.
annotation, we can implement our Function as a POJO method. SDG appropriately handles registering this POJO method
as a proper Function with {geode-name}.
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
@@ -88,8 +88,8 @@ interface EligibilityDeterminationExecution {
----
====
We can then inject the `EligibilityDeterminationExecution` into our `FinancialLoanApplicationService`, as we would any other
object or Spring bean:
We can then inject an instance of the `EligibilityDeterminationExecution` interface into our
`FinancialLoanApplicationService`, as we would any other object or Spring bean:
.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.
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
As of Spring Boot for {geode-name} (SBDG) 1.3, you can declare {geode-name} properties from
`gemfire.properties` in a Spring Boot `application.properties` file.
As of Spring Boot for {geode-name} (SBDG) 1.3, you can declare {geode-name} properties from `gemfire.properties`
in Spring Boot `application.properties`.
TIP: See the {apache-geode-docs}/reference/topics/gemfire_properties.html[User Guide]
for a complete list of valid {geode-name} properties.
TIP: See the {apache-geode-docs}/reference/topics/gemfire_properties.html[User Guide] for a complete list
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`.
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.
It is illegal to declare properties in a `gemfire.properties` file that are not valid Geode Properties, even if those
properties are prefixed with a different qualifier (such as `spring.*`). {geode-name}
throws an `IllegalArgumentException` for invalid properties.
All of the properties declared in the preceding example correspond to valid Geode properties. It is illegal to declare
properties in `gemfire.properties` that are not valid Geode properties, even if those properties are prefixed with a
different qualifier (such as `spring.*`). {geode-name} throws an `IllegalArgumentException` for invalid properties.
Consider the following `gemfire.properties` file with an `invalid-property`:
@@ -48,7 +47,7 @@ invalid-property=TEST
{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]
----
@@ -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,
such as Spring Boot `application.properties`.
Additionally, because of {geode-name}'s constraint on properties, you can not use the full power of
Spring Boot when you compose `application.properties`.
Additionally, because of {geode-name}'s constraint on properties, you cannot use the full power of Spring Boot when you
compose `application.properties`.
You can include certain properties based on a Spring profile while excluding other properties.
This is essential when properties are environment- or context-specific.
You can include certain properties based on a Spring profile while excluding other properties. This is essential when
properties are environment- or context-specific.
Spring Data for {geode-name} (SDG) already provide a wide range of properties mapping to
{geode-name} properties.
Spring Data for {geode-name} already provides a wide range of properties mapping to {geode-name} properties.
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>>.
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]
----
@@ -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.cache.log-level=TRACE
spring.data.gemfire.stats.enable-time-statistics=true
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`
(`groups` in `gemfire.properties`). This is partly due to the fact that many {geode-name} properties are
applicable only when configured on the server (such as `groups` or `enforce-unique-host`).
However, some {geode-name} properties have no equivalent SDG property, such as `gemfire.groups` (`groups` in
`gemfire.properties`). This is partly due to the fact that many {geode-name} properties are applicable only when
configured on the server (such as `groups` or `enforce-unique-host`).
TIP: See the `@EnableGemFireProperties` annotation
({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.
@@ -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 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`
directly, as follows:
Therefore, as of SBDG 1.3, you can now declare {geode-name} properties in Spring Boot `application.properties` directly,
as follows:
.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:
* 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.
* 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 also use property placeholders with Geode Properties
(such as `gemfire.log-level=${external.log-level.property}`).
* You can also use property placeholders with Geode properties (such as
`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
Spring Boot `application.properties` file. This indicates that the property belongs to {geode-name}. Without the
`gemfire.` prefix, the property is not appropriately applied to the {geode-name} cache instance.
However, SBDG requires that the Geode property must have the `gemfire.` prefix in Spring Boot `application.properties`.
This indicates that the property belongs to {geode-name}. Without the `gemfire.` prefix, the property is not
appropriately applied to the {geode-name} cache instance.
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`.
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
====
@@ -174,6 +173,7 @@ gemfire.non-existing-property=TEST
The resulting warning in the log would read:
.Invalid Geode Property Warning Message
====
[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:
.Invalide Geode Property Value Warning Message
====
[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
environment) with Spring profiles.
With regards to the third point mentioned earlier, you can now compose and declare Geode properties based on a context
(such as your application environment) using Spring profiles.
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
====
[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=profile1,profile2,...,profileN`
If both `spring.data.gemfire.*` properties and the matching {geode-name} properties are declared in Spring Boot
`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`
files and you enable more than one Spring Profile at time, the last property declaration wins. In the example shown
earlier, the value for `gemfire.groups` would be `PROD` when `-Dspring.profiles.active=qa,prod` is configured.
If a property is specified more than once, as would potentially be the case when composing multiple Spring Boot
`application.properties` files and you enable more than one Spring profile at time, the last property declaration wins.
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`:
@@ -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
declared in `application.properties`. The matching SDG property overrides the {geode-name} property when duplicates
The `durable-client-id` is `987`. It does not matter which order the SDG or {geode-name} properties are declared in
Spring Boot `application.properties`. The matching SDG property overrides the {geode-name} property when duplicates
are found.
Finally, you cannot refer to Geode Properties declared in Spring Boot `application.properties` with the
SBDG `GemFireProperties` class (see the {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/GemFireProperties.html[Javadoc]).
Finally, you cannot refer to Geode properties declared in Spring Boot `application.properties` with the SBDG
`GemFireProperties` class (see the {spring-boot-data-geode-javadoc}/org/springframework/geode/boot/autoconfigure/configuration/GemFireProperties.html[Javadoc]).
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`
in the annotation by setting `@SpringBootTest(properties = { "gemfire.name=TestCacheName" })`
for testing purposes instead of declaring the property in a separate `application.properties` file.
TIP: You can declare `application.properties` in the `@SpringBootTest` annotation. For example, you could have declared
`gemfire.name` in the annotation by setting `@SpringBootTest(properties = { "gemfire.name=TestCacheName" })`
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.
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>>.

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.
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
by including several extensions with enhanced functionality to offer an experience familiar to Spring users
inside a Spring context.
`org.springframework.geode:apache-geode-extensions` module and library builds on {geode-name}'s APIs by including
several extensions with enhanced functionality to offer an experience familiar to Spring users inside a Spring context.
TIP: Spring Data for {geode-name} (SDG) also {spring-data-geode-docs-html}/#apis[includes] additional extensions to
{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
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
(`Cache`) 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
easy, since it auto-configures a `ClientCache` instance, <<geode-clientcache-applications,by default>>.
or a {apache-geode-docs}/topologies_and_comm/p2p_configuration/chapter_overview.html[peer member or node] (`Cache`) in
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 will be a client. SBDG makes this decision easy,
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.
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)
====
@@ -71,13 +71,13 @@ abstract class SimpleCacheResolver {
----
====
`SimpleCacheResolver` adheres to https://en.wikipedia.org/wiki/SOLID[SOLID OO Principles]. This class is abstract and
extensible so that you can change the algorithm used to resolve client or peer cache instances as well as mock its methods
in unit tests.
`SimpleCacheResolver` adheres to https://en.wikipedia.org/wiki/SOLID[SOLID OO Principles]. This class is abstract
and extensible so that you can change the algorithm used to resolve client or peer cache instances as well as mock
its methods in unit tests.
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
`Optional.EMPTY`. The behavior of `resolvePeerCache()` is similar.
the cache instance is a "`client.`" If a cache exists but is a "`peer`" cache instance, `resolveClientCache()`
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
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`]
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
or a peer, one of the more useful functions is to extract all the values from a region.
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.
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
the `Region` appropriately regardless of whether the `Region` is a client or apeer. This distinction is
important, since client `PROXY` regions store no values.
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
the `Region` appropriately regardless of whether the `Region` is a client or a peer. This distinction is important,
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
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
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,
[`PARTITION`] Region can prove quite detrimental, especially in production. Getting all values from a Region can be
useful during testing.
[[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
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,
`DiskStore` instances, and so on). All previous cache objects are now invalid, and their references are stale.
the cluster. Once reconnected, the peer member must rebuild all cache objects (`Cache`, `Region` instances, `Index`
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
beans declared in and managed by the Spring container. Those beans may be injected and used in other framework and
application components. For instance, `Region` instances are injected into SDG's `GemfireTemplate`, Spring Data repositories
and possibly application-specific data access objects (https://en.wikipedia.org/wiki/Data_access_object[DAOs]).
In a Spring context, this is particularly problematic since most {geode-name} objects are _Singleton_ beans declared in
and managed by the Spring container. Those beans may be injected and used in other framework and application components.
For instance, `Region` instances are injected into SDG's `GemfireTemplate`, Spring Data Repositories and possibly
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
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
{geode-name} `MembershipListener` API and corresponding events are "`internal`".
Spring `ApplicationContext` is "`refreshed`". In fact, there is no way to even know that this event has occurred, since
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`,
`Index`, `DiskStore`, `AsyncEventQueue`, `GatewayReceiver`, `GatewaySender`, and others) used by Spring. The proxies
would know how to obtain a "`fresh`" reference on a reconnect event. However, this turns out to be more problematic than
it is worth. It is easier to "`refresh`" the Spring `ApplicationContext`, although doing so is no less expensive. Neither way is
NOTE: The Spring team explored the idea of creating proxies for all types of cache objects (`Cache`, `Region`, `Index`,
`DiskStore`, `AsyncEventQueue`, `GatewayReceiver`, `GatewaySender`, and others) used by Spring. The proxies would know
how to obtain a fresh reference on a reconnect event. However, this turns out to be more problematic than it is worth.
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]
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/MembershipEvent.html[`MembershipEvent`]
The abstract `MembershipListenerAdapter` class implements {geode-name}'s `org.apache.geode.distributed.internal.MembershipListener` interface
to simplify the event handler method signatures by using an appropriate `MembershipEvent` type
to encapsulate the actors in the event.
The abstract `MembershipListenerAdapter` class implements {geode-name}'s `org.apache.geode.distributed.internal.MembershipListener`
interface to simplify the event handler method signatures by using an appropriate `MembershipEvent` type to encapsulate
the actors in the event.
The abstract `MembershipEvent` class is further subclassed to represent specific membership event types that occur
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
{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
Spring context in order to refresh the Spring `ApplicationContext`.
Spring container in order to refresh the Spring `ApplicationContext`.
[[geode-api-extensions-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.
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
new `PdxInstance` and copy from the existing `PdxInstance`. Unfortunately, the {geode-name} API offers no assistance.
It is also not possible to use PDX in a client, local-only mode without a server, since the PDX type registry is only
available and managed on servers in a cluster. All of this leaves much to be desired.
existing `PdxInstance` by adding or removing fields, since doing so would require a new PDX type. In this case, you must
create a new `PdxInstance` and copy from an existing `PdxInstance`. Unfortunately, the {geode-name} API offers no help
in this regard. It is also not possible to use PDX in a client, local-only mode without a server, since the PDX type
registry is only available and managed on servers in a cluster.
[[geode-api-extensions-pdx-builder]]
==== `PdxInstanceBuilder`
In such cases, SBDG conveniently provides the
{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`:
.`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
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
model type.
method fails when converting the JSON generated from PDX back into a POJO for any practical application domain model
type.
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.
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
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 --
the `PdxInstanceWrapper` class provides the `getIdentifier()` method to return the ID of the `PdxInstance` directly.
`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 `getIdentifier()` method is smart in that it first iterates the fields of the `PdxInstance`, asking each field if it is
the identity field. If no field was marked as the `identity` field, the algorithm searches for a field named `id`.
If no field with the name `id` exists, the algorithm searches for a metadata field called `@identifier`, which
refers to the field that is the identity field of the `PdxInstance`.
The `getIdentifier()` method is smart in that it first iterates the fields of the `PdxInstance`, asking each field if it
is the identity field. If no field was marked as the identity field, the algorithm searches for a field named `id`. If
no field with the name `id` exists, the algorithm searches for a metadata field called `@identifier`, which refers to
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
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.
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
{geode-name} itself (that is, `PdxInstanceImpl`), which has a tight coupling to the PDX type registry. An `Exception` is
thrown if you try to store instances of your own `PdxInstance` implementation.
value in a Region. {geode-name} assumes all `PdxInstance` objects are an implementation created by {geode-name} itself
(that is, `PdxInstanceImpl`), which has a tight coupling to the PDX type registry. An `Exception` is thrown if you try
to store instances of your own `PdxInstance` implementation.
[[geode-api-extensions-pdx-adapter]]
==== `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
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
`PdxInstance`, particularly when {geode-name}'s `read-serialized` PDX configuration property is set to `true` and only
an object is available in the current context.
This might be true when calling a method with a parameter expecting an argument of, or returning an instance of,
type `PdxInstance`, particularly when {geode-name}'s `read-serialized` PDX configuration property is set to `true`
and only an object is available in the current context.
Under the hood, SBDG's `ObjectPdxInstanceAdapter` class uses Spring'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/WritablePdxInstance.html[`WritablePdxInstance`] API, obtained from
{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
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
introspected in this case, given that the underlying `Object` backing the `PdxInstance` is a POJO.
{spring-data-commons-javadoc}/org/springframework/data/annotation/Id.html[`@Id`] mapping annotation,
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` 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:
@@ -385,11 +388,12 @@ class ObjectPdxInstanceAdapterTest {
[[geode-api-extensions-security]]
=== Security
For testing purposes, SBDG provides a test implementation of {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.
For testing purposes, SBDG provides a test implementation of
{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.
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
supplies matching credentials for both the username and password.
{geode-name}'s {apache-geode-javadoc}/org/apache/geode/security/AuthInitialize.html[`AuthInitialize`] interface,
which supplies matching credentials for both the username and password.

View File

@@ -2,30 +2,30 @@
== Logging
: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
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
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
`gemfire.properties`, in Spring Boot `application.properties`, or even as a JVM System Property (`-Dgemfire.log-level`).
However, now, in order to get any log output from {geode-name} whatsoever, {geode-name} requires a logging provider
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 `gemfire.properties`,
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]
for a complete list of valid `Properties`, including the `Properties` used to configure logging.
TIP: See {geode-name}'s {apache-geode-docs}/reference/topics/gemfire_properties.html[documentation] for a complete list
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`]
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
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.
By way of example, and to make this concrete, *none* of the following approaches have any effect on
{geode-name} logging:
By way of example, and to make this concrete, *none* of the following approaches have any effect on {geode-name} logging:
.Command-line configuration
====
@@ -50,7 +50,6 @@ log-level=INFO
[source,properties]
----
spring.data.gemfire.cache.log-level=DEBUG
spring.data.gemfire.logging.level=DEBUG
----
====
@@ -62,7 +61,7 @@ spring.data.gemfire.logging.level=DEBUG
@SpringBootApplication
@EnableLogging(logLevel = "DEBUG")
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}?
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.
. (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.
+
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
dependency as well.
logging provider or implementation, you must include the `org.apache.logging.log4j.log4j-to-slf4j` adapter or
bridge JAR as well.
+
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
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
classpath or in the filesystem. Alternatively, you can use other means to configure your logging provider and get
{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
(`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,
it covers steps 1 and 2 above.
The `spring-boot-starter-logging` dependency declares Logback as the logging provider and automatically adapts
(or bridges) `java.util.logging` (JUL) and Apache Log4j to SLF4J. However, you still need to supply logging provider
configuration (such as a `logback.xml` file for Logback) to configure logging not only for your Spring Boot
application but for {geode-name} as well.
The `spring-boot-starter-logging` dependency declares Logback as the logging provider and automatically adapts (bridges)
`java.util.logging` (JUL) and Apache Log4j to SLF4J. However, you still need to supply logging provider configuration
(such as a `logback.xml` file for Logback) to configure logging not only for your Spring Boot application but for
{geode-name} as well.
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.
Unlike {geode-name}'s default Log4j XML configuration file (`log4j2.xml`), SBDG's provided `logback.xml`
configuration file is properly parameterized, letting you adjust log levels as well as add appenders.
Unlike {geode-name}'s default Log4j XML configuration file (`log4j2.xml`), SBDG's provided `logback.xml` configuration
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
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]]
==== 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,
you may want only to 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.
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 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.
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]
----
@@ -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}
for backwards compatibility. By default, it logs output at `INFO`. This logger's use should be largely unnecessary.
The `com.gemstone.gemfire` Logger covers old GemFire components that are still present in {geode-name} for backwards
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`.
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
(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
`spring.boot.data.gemfire.log.level` property. You can independently configure the `org.jgroups` logger by setting the
`spring.boot.data.gemfire.jgroups.log.level` property.
You can configure the log level for the `com.gemstone.gemfire` and `org.apache.geode` Loggers by setting
the `spring.boot.data.gemfire.log.level` property. You can independently configure the `org.jgroups` Logger by setting
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:
.Setting the log-level from the command-line
.Setting the log-level from the CLI
====
[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).
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]
----
@@ -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:
.Setting log-level using SDG 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
SBDG `1.3` or later.
If you previously used either of these SDG-based logging properties, they continue to work as designed in SBDG `1.3`
or later.
[[geode-logging-configuration-composition]]
==== Composing Logging Configuration
As mentioned earlier, SBDG lets you compose your own logging configuration from SBDG's default Logback
configuration metadata.
As mentioned earlier, SBDG lets you compose your own logging configuration from SBDG's default Logback configuration
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.
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]]
==== CompositeAppender
The `org.springframework.geode.logging.slf4j.logback.CompositeAppender` class is an implementation of Logback
`Appender` and the https://en.wikipedia.org/wiki/Composite_pattern[composite software design pattern].
The `org.springframework.geode.logging.slf4j.logback.CompositeAppender` class is an implementation of the Logback
`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`
====
[source,java]
----
class LoggingConfiguration {
void composeApenders() {
Appender<ILoggingEvent> compositeAppender() {
ConsoleAppender<ILoggingEvent> consoleAppender = new ConsoleAppender<>();
FileAppender<ILoggingEvent> fileAppender = new FileApender<>();
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`
====
[source,java]
----
class LoggerConfiguration {
void registerAppenderOnLogger() {
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
`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
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
`ConsoleAppender`, a `FileAppender`, a `SocketAppender`, or others. By default, the `DelegatingAppender` delegates
to the `NOPAppender`, thereby doing no actual work.
implementation that wraps another Logback `Appender` or collection of `Appenders`, such as the `ConsoleAppender`,
a `FileAppender`, a `SocketAppender`, or others. By default, the `DelegatingAppender` delegates to the `NOPAppender`,
thereby doing no actual work.
By default, SBDG registers the `org.springframework.geode.logging.slfj4.logback.DelegatingAppender` with
the ROOT `Logger`, which can be useful for testing purposes.
By default, SBDG registers the `org.springframework.geode.logging.slfj4.logback.DelegatingAppender` with the ROOT
`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:
@@ -309,6 +314,7 @@ With a reference to a `DelegatingAppender`, you can add any `Appender` (even a `
[source,java]
----
class LoggerConfiguration {
void setupDelegation() {
ConsoleAppender consoleAppender = new ConsoleAppender();
@@ -331,12 +337,12 @@ class LoggerConfiguration {
[[geode-logging-slf4j-logback-api-support-appender-string]]
==== 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`.
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
log messages were not logged.
a `Logger` used by certain application components logged messages at the appropriately configured log level
while other log messages were not logged.
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()`.
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}
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
to define basic CRUD and simple query data access operations by specifying the contract of those data access
operations in a Java interface.
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.
Spring Boot for {geode-name} auto-configures the Spring Data for {geode-name} {spring-data-geode-docs-html}/#gemfire-repositories[repository extension]
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.
{spring-data-commons-docs-html}/#repositories[Spring Data Repositories] provide a convenient and powerful way to define
basic CRUD and simple query data access operations by specifying the contract of those data access operations in a Java
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-data-geode-javadoc}/org/springframework/data/gemfire/mapping/annotation/Region.html[`@Region`] mapping
annotation:
Spring Boot for {geode-name} auto-configures the Spring Data for {geode-name}
{spring-data-geode-docs-html}/#gemfire-repositories[Repository extension]
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
====
[source,java]
----
package example.app.books.model;
package example.app.crm.model;
@Region("Customers")
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`
====
[source,java]
----
package example.app.books.repo;
package example.app.crm.repo;
interface CustomerRepository extends CrudRepository<Customer, Long> {
@@ -80,6 +85,6 @@ class SpringBootApacheGeodeClientCacheApplication {
----
====
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]
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]
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.
Some examples focus on specific use cases (such as (HTTP) session state caching), while other examples show how
SBDG works under the hood, to give you a better understanding of what is actually happening and how to debug problems
with your {geode-name}, Spring Boot applications.
Some examples focus on specific use cases (such as (HTTP) session state caching), while other examples show how SBDG
works under the hood, to give you a better understanding of what is actually happening and how to debug problems with
your Spring Boot {geode-name} applications.
.Example Spring Boot applications using {geode-name}
|===
| Guide | Description | Source
| 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
applications with Spring Boot.
| Explains how to get started quickly, easily, and reliably building {geode-name} powered applications with Spring Boot.
| {github-samples-url}/intro/getting-started[Getting Started]
| 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]
| 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
in Spring Boot applications.
| Explains how to configure auth and TLS with SSL when you use {geode-name} in your Spring Boot applications.
| {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}]
| 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]
| 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.
This sample builds on the look-aside caching sample, described earlier.
| 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.
| {github-samples-url}/caching/inline[Inline Caching]
| 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
inline caching. This sample builds on the look-aside caching and inline caching samples, described earlier.
| 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 and inline caching samples.
| {github-samples-url}/caching/inline-async[Asynchronous Inline Caching]
| 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.
This sample builds on the look-aside caching sample, described earlier.
| 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.
| {github-samples-url}/caching/near[Near Caching]
| 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.
This sample builds on the look-aside caching sample, described earlier, and is the fourth and final leg in our study
of caching patterns.
| Explains how to enable and use Spring's Cache Abstraction with {geode-name} as the caching provider for multi-site
caching. This sample builds on the look-aside caching sample.
| {github-samples-url}/caching/multi-site[Multi-Site Caching]
| 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]
|===

View File

@@ -5,6 +5,9 @@
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.
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}.
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
{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
your client to server data exchanges and operations.
and role-based {apache-geode-docs}/managing/security/authorization_overview.html[authorization] to secure your client to
server data exchanges and operations.
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
{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].
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},
it makes short work of enabling auth in both your clients and servers.
When you use Spring Boot for {geode-name}, which builds Spring Data for {geode-name}, it makes short work of
enabling auth in both your clients and servers.
[[geode-security-auth-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
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:
.Declaring an Apache Shiro realm
.Declaring an Apache Shiro Realm
====
[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
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
enabled.
When an Apache Shiro Realm (such as `DefaultLdapRealm`) is declared and registered in the Spring `ApplicationContext`
as a Spring bean, Spring Boot automatically detects this `Realm` bean (or `Realm` beans if more than one is configured),
and the servers in the {geode-name} cluster are automatically configured with authentication and authorization enabled.
Alternatively, you can provide a custom, application-specific implementation of {geode-name}'s
{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
the servers in the {geode-name} cluster with authentication and authorization enabled.
Spring Boot discovers your custom, application-specific `SecurityManager` implementation and configures the servers
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
{geode-name} servers over implementing {geode-name}'s `SecurityManager` interface.
servers over implementing {geode-name}'s `SecurityManager` interface.
[[geode-security-auth-clients]]
==== Auth for Clients
When {geode-name} servers have been configured with authentication and authorization enabled, clients must
authenticate when connecting.
When servers in an {geode-name} cluster have been configured with authentication and authorization enabled, clients
must authenticate when connecting.
Spring Boot for {geode-name} makes this easy, regardless of whether you run your Spring Boot `ClientCache`
applications in a local, non-managed environment or run in a cloud-managed environment.
Spring Boot for {geode-name} makes this easy, regardless of whether you run your Spring Boot `ClientCache` applications
in a local, non-managed environment or run in a cloud-managed environment.
[[geode-security-auth-clients-non-managed]]
===== Non-Managed Auth for Clients
To enable Auth for clients that connect to a secure {geode-name} cluster, you need only set a username
and password in your Spring Boot `application.properties` file:
To enable auth for clients that connect to a secure {geode-name} cluster, you need only set a username and password
in Spring Boot `application.properties`:
.Spring Boot `application.properties` for the client
====
[source,txt]
----
@@ -114,21 +118,22 @@ Spring Boot for {geode-name} handles the rest.
[[geode-secuirty-auth-clients-managed]]
===== Managed Auth for Clients
Enabling auth for clients that connect to a Pivotal Cloud Cache (PCC) service instance in Pivotal CloudFoundry (PCF)
is even easier: You need do nothing.
Enabling auth for clients that connect to a {pivotal-cloudcache-name} service instance (PCC)
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,
Spring Boot for {geode-name} extracts the required auth credentials from the environment that you set up when you
provisioned a PCC service instance in your PCF organization and space. PCC automatically assigns two users with roles of
`cluster_operator` and `developer`, respectively, to any Spring Boot application bound to the PCC service instance.
If your Spring Boot application uses SBDG and is bound to PCC, when you deploy (that is, `cf push`) your application
to PCF, Spring Boot for {geode-name} extracts the required auth credentials from the environment that you set up when
you provisioned a PCC service instance in your PCF organization and space. PCC automatically assigns two users with
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.
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
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
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.
@@ -138,14 +143,14 @@ when you use PCC and PCF.
[[geode-security-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
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,
between HTTP clients when you use the developer REST API or Pulse, between peers in the cluster, and when you use the WAN Gateway
to connect multiple sites (that is, clusters).
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 to connect multiple sites (clusters).
Spring Data for {geode-name} provides
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.
{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].
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.
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
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
====
@@ -196,14 +201,14 @@ If your `trusted.keystore` file is secured with a password, you need to addition
----
# 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
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]
----
@@ -222,11 +227,11 @@ annotation for all the configuration attributes and the corresponding properties
[[geode-security-encryption]]
=== Securing Data at Rest
Currently, neither {geode-name} nor Spring Boot nor Spring Data for {geode-name} offer any support for securing your data
while at rest (for example, when your data has been overflowed or persisted to disk).
Currently, neither {geode-name} nor Spring Boot nor Spring Data for {geode-name} offer any support for securing your
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
encryption, which is usually highly contextual and technology-specific.
To secure data at rest when using {geode-name}, with or without Spring, you must employ third-party solutions, such as
disk encryption, which is usually highly contextual and technology-specific.
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].

View File

@@ -1,37 +1,37 @@
[[geode-session]]
== Spring Session
:geode-name: {apache-geode-name}
:pcc-name: Pivotal Cloud Cache
:vmw-tas-name: VMware Tanzu Application Service
:pcc-name: {pivotal-cloudcache-name}
: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.
{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
way and provide session IDs in HTTP headers to work with RESTful APIs.
information. It has the ability to replace the `javax.servlet.http.HttpSession` in an application container-neutral way
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
and reactive Spring WebFlux WebSessions.
Furthermore, Spring Session provides the ability to keep the `HttpSession` alive even when working with `WebSockets`
and reactive Spring WebFlux `WebSessions`.
A full discussion of Spring Session is beyond the scope of this document. You can learn more
by reading the {spring-session-docs}[docs] and reviewing the {spring-session-docs}/#samples[samples].
A complete discussion of Spring Session is beyond the scope of this document. You can learn more by reading
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}
as the user's session information management provider and store when {spring-session-data-gemfire-website}[Spring Session for {geode-name}]
is on your Spring Boot application's classpath.
Spring Boot for {geode-name} provides auto-configuration support to configure {geode-name} as the session management
provider and store when {spring-session-data-gemfire-website}[Spring Session for {geode-name}] is on your Spring Boot
application's classpath.
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]
to see Spring Session for {geode-name} in action.
TIP: See the corresponding sample link:guides/caching-http-session.html.html[guide]
and {github-samples-url}/caching/http-session[code] to see Spring Session for {geode-name} in action.
[[geode-session-configuration]]
=== Configuration
You need do nothing special to use {geode-name} as a Spring Session provider,
managing the (HTTP) session state of your Spring Boot application.
You need do nothing special to use {geode-name} as a Spring Session provider implementation, managing the (HTTP) session
state of your Spring Boot application.
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`
as needed by your application:
You can then create application-specific Spring Web MVC `Controllers` to interact with the `HttpSession` as needed
by your application:
.Application Controller using HttpSession
.Spring Boot Application `Controller` using `HttpSession`
====
[source,java]
----
@@ -105,16 +105,18 @@ The `HttpSession` is replaced by a Spring managed `Session` that is stored in {g
[[geode-session-configuration-custom]]
=== Custom Configuration
By default, Spring Boot for {geode-name} (SBDG) applies reasonable and sensible defaults when configuring
{geode-name} as the provider in Spring Session.
By default, Spring Boot for {geode-name} (SBDG) applies reasonable and sensible defaults when configuring {geode-name}
as the provider in Spring Session.
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}
region that manages the (HTTP) Session state when the Spring Boot application is using a `ClientCache`, which it does
`ClientRegionShortcut.PROXY` as the data management policy for the {geode-name} client Region that managing the (HTTP)
session state when the Spring Boot application is using a `ClientCache`, which it does
by <<geode-clientcache-applications,default>>.
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]]
==== 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
management provider.
You can specify any of these properties in a Spring Boot `application.properties` file to adjust Spring Session's
configuration when using {geode-name}.
You can specify any of these properties in Spring Boot `application.properties` to adjust Spring Session's configuration
when using {geode-name}.
In addition to the properties provided in and by Spring Session for {geode-name}, Spring Boot for {geode-name}
also recognizes and respects the `spring.session.timeout` property and the `server.servlet.session.timeout`
property, as discussed {spring-boot-docs-html}/boot-features-session.html[the Spring Boot documentation].
In addition to the properties provided in and by Spring Session for {geode-name}, Spring Boot for {geode-name} also
recognizes and respects the `spring.session.timeout` property and the `server.servlet.session.timeout` property, as
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
`spring.session.timeout`, which takes precedence over `server.servlet.session.timeout` when any combination
of these properties have been simultaneously configured in the Spring `Environment` of your application.
`spring.session.timeout`, which takes precedence over `server.servlet.session.timeout` when any combination of
these properties have been simultaneously configured in the Spring `Environment` of your application.
[[geode-session-configuration-custom-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
the configuration of Spring Session when you use {geode-name}.
The `SpringSessionGemFireConfigurer`, when declared in the Spring `ApplicationContext`, takes precedence over any of the
Spring Session (for {geode-name}) configuration properties and effectively overrides them when both
are present.
The `SpringSessionGemFireConfigurer`, when declared in the Spring `ApplicationContext`, takes precedence over any of
the Spring Session (for {geode-name}) configuration properties and effectively overrides them when both are present.
More information on using the `SpringSessionGemFireConfigurer` can be found in the
{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]]
=== 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}.
In certain cases, you may be using another Spring Session provider, such as Redis, to cache and manage 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) `HttpSession` state management.
There may be cases where you do not want your Spring Boot application to manage (HTTP) session state by using
{geode-name}.
Either way, you can specifically call out your Spring Session provider by using the `spring.session.store-type` property
in `application.properties`:
In certain cases, you may be using another Spring Session provider implementation, such as Redis, to cache and manage
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]
----
@@ -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
do the following:
If you prefer not to use Spring Session to manage your Spring Boot application's (HTTP) session state at all, you can do
the following:
.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,
you might use Redis to cache your application's (HTTP) Session state while using {geode-name} as your
application's persistent store (system of record).
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 application's
transactional persistent store (System of Record).
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
@@ -198,16 +202,16 @@ Spring Boot for {geode-name} is set up to handle either of these property values
[[geode-session-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
cluster of {geode-name} servers or to connect to a cluster of servers in a {pcc-name} service instance managed by
a {vmw-tas-name} (TAS) environment, the setup is the same.
Whether you use Spring Session in a Spring Boot, {geode-name} `ClientCache` application to connect to an standalone,
externally managed cluster of {geode-name} servers or to connect to a cluster of servers in a {pcc-name} service
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)
Session state when your Spring Boot application is a `ClientCache` application in a client/server topology.
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 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`:
.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
the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class:
Alternatively, you can set the name of the cache Region used to store and manage (HTTP) session state by explicitly
declaring the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class:
.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
cluster somehow.
Once you decide on the cache Region name used to store and manage (HTTP) sessions, you must create the cache Region
in the cluster somehow.
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
the application classpath (for example, `spring-geode-starter-session`) or you explicitly declare
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 the application classpath (for example, `spring-geode-starter-session`) or you explicitly declare
the `@EnableGemFireHttpSession` annotation on your main `@SpringBootApplication` class.
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
====
@@ -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.
In this case, we created an idle expiration policy with a timeout of `1800` seconds (30 minutes), after which
the entry (session object) `invalidated`.
In this case, we created an idle expiration policy with a timeout of `1800` seconds (30 minutes), after which the entry
(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.
The servlet container's (HTTP) session expiration configuration is not used, since Spring Session replaces
the servlet container's session management capabilities with its own, and Spring Session delegates this behavior
to the individual providers, such as {geode-name}.
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 session management capabilities with its own, and Spring Session delegates this behavior to the individual
providers, such as {geode-name}.
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,
@@ -274,7 +278,7 @@ which is meta-annotated with SDG's `@EnableClusterConfiguration` annotation:
----
@SpringBootApplication
@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]
for more detail.
However, you cannot currently send expiration policy configuration metadata to the cluster. Therefore,
you must manually alter the cache region to set the expiration policy:
However, you cannot currently send expiration policy configuration metadata to the cluster. Therefore, you must manually
alter the cache Region to set the expiration policy:
.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
and manage user (HTTP) session state in the cluster. This works for either standalone, externally managed {geode-name}
clusters or when you use PCC running in a {vmw-tas-name} environment.
Now your Spring Boot `ClientCache` application that uses Spring Session in a client/server topology is configured to
store and manage user (HTTP) session state in the cluster. This works for either standalone, externally managed
{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}.
For instance, you can use the {apache-geode-javadoc}/org/apache/geode/cache/Region.html[Region API]
directly. If you are driven by the application's domain context, you can use the power of
For instance, you can use the {apache-geode-javadoc}/org/apache/geode/cache/Region.html[Region API] directly. If you
are driven by the application's domain context, you can use the power of
{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
undesirable and unnecessary. While using Spring Data Repositories provides a very powerful and convenient abstraction,
you give up the flexibility provided by a lower-level API.
While the Region API offers flexibility, it couples your application to {geode-name}, which is usually undesirable
and unnecessary. While using Spring Data Repositories provides a very powerful and convenient abstraction, you give up
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
the entire Spring portfolio.
A good compromise is to use the https://en.wikipedia.org/wiki/Template_method_pattern[Template software design pattern].
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`]
and {spring-framework-javadoc}/org/springframework/jms/core/JmsTemplate.html[`JmsTemplate`].
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`],
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`].
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:
* A simple, consistent, and convenient data access API to perform CRUD and basic query operations on cache regions.
* Use of Spring Framework's consistent data access {spring-framework-docs}/data-access.html#dao-exceptions[exception hierarchy].
* 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].
* 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
region present in the {geode-name} cache.
Given these advantages, Spring Boot for {geode-name} (SBDG) auto-configures `GemfireTemplate` beans for each Region
present in the {geode-name} cache.
Additionally, SBDG is careful not to create a `GemfireTemplate` if you have already declared a `GemfireTemplate`
bean in the Spring `ApplicationContext` for a given region.
Additionally, SBDG is careful not to create a `GemfireTemplate` if you have already declared a `GemfireTemplate` bean
in the Spring `ApplicationContext` for a given Region.
[[geode-data-access-region-templates-explicit-declaration]]
=== Explicitly Declared Regions
Consider an explicitly declared region bean definition:
Consider an explicitly declared Region bean definition:
. Explicitly Declared Region Bean Definition
====
[source,java]
----
@Configuration
class GemFireConfiguration {
class GeodeConfiguration {
@Bean("Example")
ClientRegionFactoryBean<?, ?> exampleRegion (GemFireCache gemfireCache) {
// ...
}
@Bean("Example")
ClientRegionFactoryBean<?, ?> exampleRegion(GemFireCache gemfireCache) {
// ...
}
}
----
====
SBDG automatically creates a `GemfireTemplate` bean for the `Example` region by using a bean name `exampleTemplate`.
SBDG names the `GemfireTemplate` bean after the region by converting the first letter in the region's name
to lower case and appending `Template` to the bean name.
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 to lower case
and appending `Template` to the bean name.
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
class ExampleDataAccessObject {
@Autowired
@Qualifier("exampleTemplate")
private GemfireTemplate exampleTemplate;
@Autowired
@Qualifier("exampleTemplate")
private GemfireTemplate exampleTemplate;
}
----
====
You should use the `@Qualifier` annotation to qualify which
`GemfireTemplate` bean you are specifically referring, especially if you have more than one region, as demonstrated earlier.
You should use the `@Qualifier` annotation to qualify which `GemfireTemplate` bean you are specifically referring,
especially if you have more than one Region bean definition.
[[geode-data-access-region-templates-entity-defined]]
=== 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:
.Customer class
====
[source,java]
----
@Region("Customers")
class Customer {
// ...
// ...
}
----
====
Further consider the following configuration:
.Apache Geode Configuration
====
[source,java]
----
@Configuration
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
class GeodeConfiguration {
// ...
// ...
}
----
====
@@ -114,92 +117,96 @@ class GeodeConfiguration {
SBDG auto-configures a `GemfireTemplate` bean for the `Customers` Region named `customersTemplate`, which you can then
inject into an application component:
.CustomerService application component
====
[source,java]
----
@Service
class CustomerService {
@Bean
@Qualifier("customersTemplate")
private GemfireTemplate customersTemplate;
@Bean
@Qualifier("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.
[[geode-data-access-region-templates-caching-defined]]
=== 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
{geode-name}, one requirement is to configure regions for each of the caches specified in the
When you use Spring Framework's {spring-framework-docs}/integration.html#cache[Cache Abstraction] backed by {geode-name},
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.
Fortunately, SBDG makes enabling and configuring caching easy and <<geode-caching-provider,automatic>>.
Consider the following cacheable application service component:
.Cacheable `CustomerService` class
====
[source,java]
----
@Service
class CacheableCustomerService {
@Bean
@Qualifier("customersByNameTemplate")
private GemfireTemplate customersByNameTemplate;
@Bean
@Qualifier("customersByNameTemplate")
private GemfireTemplate customersByNameTemplate;
@Cacheable("CustomersByName")
public Customer findBy(String name) {
return toCustomer(customersByNameTemplate.query("name = " + name));
}
@Cacheable("CustomersByName")
public Customer findBy(String name) {
return toCustomer(customersByNameTemplate.query("name = " + name));
}
}
----
====
Further consider the following configuration:
.Apache Geode Configuration
====
[source,java]
----
@Configuration
@EnableCachingDefinedRegions
class GemFireConfiguration {
class GeodeConfiguration {
@Bean
public CustomerService customerService() {
return new CustomerService();
}
@Bean
public CustomerService customerService() {
return new CustomerService();
}
}
----
====
SBDG auto-configures a `GemfireTemplate` bean named `customersByNameTemplate` to perform data access operations
on the `CustomersByName` (`@Cacheable`) region. You can then inject the bean into any managed application component,
as shown in the preceding service component example.
SBDG auto-configures a `GemfireTemplate` bean named `customersByNameTemplate` to perform data access operations on
the `CustomersByName` (`@Cacheable`) Region. You can then inject the bean into any managed application component,
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
explicitly or implicitly, such as when using the `@EnableCachingDefineRegions` annotation.
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 `@EnableCachingDefineRegions` annotation.
WARNING: Autowiring (that is, injecting) `GemfireTemplate` beans auto-configured by SBDG
for caching-defined regions into your application components does not always work. This has to do with the Spring
container bean creation process. 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
when autowiring does not.
WARNING: Autowiring (that is, injecting) `GemfireTemplate` beans auto-configured by SBDG for caching-defined Regions
into your application components does not always work. This has to do with the Spring container bean creation process.
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 when
autowiring does not.
[[geode-data-access-region-templates-native-defined]]
=== Native-defined Regions
SBDG even auto-configures `GemfireTemplate` beans for regions that have been defined with {geode-name} native configuration
metadata, such as `cache.xml`.
SBDG even auto-configures `GemfireTemplate` beans for Regions that have been defined with {geode-name} native
configuration metadata, such as `cache.xml`.
Consider the following {geode-name} native `cache.xml`:
.Client `cache.xml`
====
[source,xml]
----
@@ -217,81 +224,47 @@ Consider the following {geode-name} native `cache.xml`:
Further consider the following Spring configuration:
.Apache Geode Configuration
====
[source,java]
----
@Configuration
@EnableGemFireProperties(cacheXmlFile = "cache.xml")
class GemFireConfiguration {
// ...
class GeodeConfiguration {
// ...
}
----
====
SBDG auto-configures a `GemfireTemplate` bean named `exampleTemplate` after the `Example` region defined in
`cache.xml`. You can inject this template as you would any other Spring-managed bean:
SBDG auto-configures a `GemfireTemplate` bean named `exampleTemplate` after the `Example` Region defined in `cache.xml`.
You can inject this template as you would any other Spring-managed bean:
.Injecting the `GemfireTemplate`
====
[source,java]
----
@Service
class ExampleService {
@Autowired
@Qualifier("exampleTemplate")
private GemfireTemplate exampleTemplate;
@Autowired
@Qualifier("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]]
=== Template Creation Rules
Fortunately, SBDG is careful not to create a `GemfireTemplate` bean for a region if a template by the same name
already exists. For example, consider the following configuration:
Fortunately, SBDG is careful not to create a `GemfireTemplate` bean for a Region if a template by the same name already
exists.
====
[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:
For example, consider the following configuration:
.Apache Geode Configuration
====
[source,java]
----
@@ -299,16 +272,58 @@ With the following configuration, SBDG is still careful not to create the Templa
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
class GeodeConfiguration {
@Bean
public GemfireTemplate vipCustomersTemplate(GemFireCache cache) {
return new GemfireTemplate(cache.getRegion("/Customers"));
}
@Bean
public GemfireTemplate customersTemplate(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.
Further consider the following example:
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.
.Customer class
====
[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}
: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
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.
[[geode-testing-unit]]
=== 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:
.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`
using Spring Boot. It does, however, mock all {geode-name} objects, such as the `Users` `Region` declared by the
`User` application entity class, which was annotated with SDG's `@Region` mapping annotation.
using Spring Boot. However, it does mock all {geode-name} objects, such as the `Users` `Region` declared by the `User`
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`
instance. In addition, SDG's `@EnableEntityDefinedRegions` annotation was used to conveniently create the {geode-name}
"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
(OQL) query (`findById`) data access operations on the `Users` `Region`.
Finally, Spring Data's Repository abstraction was used to conveniently perform basic CRUD (such as `save`) and simple
(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
the data access operations required by your Spring Boot application's business logic in an {geode-name} API-agnostic way --
that is, by using Spring's powerful programming model and constructs.
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.
TIP: By extending STDG's `org.springframework.data.gemfire.tests.integration.IntegrationTestSupport` class,
you ensure that all {geode-name} mock objects and resources are properly released after the test class runs,
thereby preventing any interference with downstream tests.
TIP: By extending STDG's `org.springframework.data.gemfire.tests.integration.IntegrationTestSupport` class, you ensure
that all {geode-name} mock objects and resources are properly released after the test class runs, thereby preventing
any interference with downstream tests.
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`
query operations involving complex OQL statements that have sophisticated predicates.
operations, it is not pragmatic to mock them all. For example, it would not be practical to mock `Region` query
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,
you can follow the advice in this section about {stdg-website}/#mocking-unsupported-region-operations[unsupported region operations].
If such functional testing is required, the test might be better suited as an integration test. Alternatively, you can
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:
@@ -101,8 +102,8 @@ TIP: See the documentation on {stdg-website}/#unit-testing-with-stdg[Unit Testin
=== Integration Testing
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
SBDG's `@EnableClusterAware` annotation to conditionally detect the presence of a {geode-name} cluster:
`@EnableGemFireMockObjects` annotation in your test configuration. You may then want to use SBDG's `@EnableClusterAware`
annotation to conditionally detect the presence of a {geode-name} cluster:
.Using `@EnableClusterAware` in test configuration
====
@@ -115,16 +116,16 @@ static class TestConfiguration { }
----
====
The SBDG `@EnableClusterAware` annotation conveniently toggles your auto-configured `ClientCache` instance
between local-only mode and client/server. It even pushes configuration metadata
(such as `Region` definitions) up to the servers in the cluster that are required by the application to persist data.
The SBDG `@EnableClusterAware` annotation conveniently toggles your auto-configured `ClientCache` instance between
local-only mode and client/server. It even pushes configuration metadata (such as `Region` definitions) up to
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 a client/server capacity. This unlocks the full capabilities of the {geode-name} data management system
in a Spring context and gets you as close as possible to production from the comfort of your IDE.
In most cases, in addition to testing with "`live`" {geode-name} objects (such as Regions), we also want to test in
a client/server capacity. This unlocks the full capabilities of the {geode-name} data management system in a Spring
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`"
{geode-name} objects in a client/server topology as follows:
Building on our example from the section on <<geode-testing-unit>>, you can modify the test to use "`live`" {geode-name}
objects in a client/server topology as follows:
.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
`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,
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
[source,java]
@@ -213,9 +215,9 @@ class SpringBootApacheGeodeIntegrationTest extends ForkingClientServerIntegratio
}
----
STDG lets you configure the server with Spring configuration, specified in the `TestGeodeServerConfiguration` class.
The Java class needs to provide a `main` method. It uses the `SpringApplicationBuilder` to bootstrap the {geode-name}
`CacheServer` application:
STDG lets you configure the {geode-name} server with Spring configuration, specified in
the `TestGeodeServerConfiguration` class. The Java class needs to provide a `main` method. It uses
the `SpringApplicationBuilder` to bootstrap the {geode-name} `CacheServer` application:
.{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
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
in mind that the test is the "`client`" in this arrangement.
We take advantage of Spring profiles in the test setup to distinguish between the client and server configuration.
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`
application in a separate JVM process. Subsequently, the STDG framework stops the server upon completion of
the tests in the test class.
application in a separate JVM process. Subsequently, the STDG framework stops the server upon completion of the tests
in the test class.
You are free to start your servers or cluster however you choose. STDG provides
this capability as a convenience for you, since it is a common concern.
You are free to start your servers or cluster however you choose. STDG provides this capability as a convenience for you,
since it is a common concern.
This test class is simple. STDG can handle much more complex test scenarios.