Merge documentation edits with documentation polish.
Resolves gh-109.
This commit is contained in:
@@ -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.
|
||||
|
||||
|=====================================================================================================================
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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`).
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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`
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
====
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>>.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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]
|
||||
|
||||
|===
|
||||
|
||||
@@ -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].
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user