SGF-768 - Full editing pass of Spring Data for Pivotal GemFire.
Edit the entire reference guide for spelling, grammar, usage, corporate voice, and similar issues. I also added an epub cover image for the epub output, once we start making epub. Resolve gh-95.
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
[[appendix-schema]]
|
||||
[appendix]
|
||||
= Spring Data for Pivotal GemFire Schema
|
||||
:resourcesDir: {basedocdir}/../resources
|
||||
|
||||
- http://www.springframework.org/schema/gemfire/spring-gemfire.xsd[Spring Data for Pivotal GemFire Core Schema (`gfe`-namespace)]
|
||||
- http://www.springframework.org/schema/gemfire/spring-data-gemfire.xsd[Spring Data for Pivotal GemFire Data Access Schema (`gfe-data`-namespace)]
|
||||
* http://www.springframework.org/schema/gemfire/spring-gemfire.xsd[Spring Data for Pivotal GemFire Core Schema (`gfe` namespace)]
|
||||
* http://www.springframework.org/schema/gemfire/spring-data-gemfire.xsd[Spring Data for Pivotal GemFire Data Access Schema (`gfe-data` namespace)]
|
||||
|
||||
BIN
src/main/asciidoc/images/epub-cover.png
Normal file
BIN
src/main/asciidoc/images/epub-cover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
10
src/main/asciidoc/images/epub-cover.svg
Normal file
10
src/main/asciidoc/images/epub-cover.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 8.7 KiB |
@@ -1,10 +1,17 @@
|
||||
= Spring Data for Pivotal GemFire Reference Guide
|
||||
Costin Leau , David Turanski , John Blum , Oliver Gierke
|
||||
Costin Leau; David Turanski; John Blum; Oliver Gierke; Jay Bryant
|
||||
:revnumber: {version}
|
||||
:revdate: {localdate}
|
||||
:linkcss:
|
||||
:doctype: book
|
||||
:docinfo: shared
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:source-highlighter: prettify
|
||||
:icons: font
|
||||
:imagesdir: images
|
||||
ifdef::backend-epub3[:front-cover-image: image:epub-cover.png[Front Cover,1050,1600]]
|
||||
:spring-data-commons-docs: {basedocdir}/../../../../spring-data-commons/src/main/asciidoc
|
||||
:toc:
|
||||
:!toc-placement:
|
||||
|
||||
(C) 2010-2018 The original authors.
|
||||
|
||||
@@ -12,39 +19,27 @@ NOTE: Copies of this document may be made for your own use and for distribution
|
||||
charge any fee for such copies and further provided that each copy contains this Copyright Notice
|
||||
whether distributed in print or electronically.
|
||||
|
||||
toc::[]
|
||||
|
||||
[[preface]]
|
||||
include::{basedocdir}/preface.adoc[]
|
||||
|
||||
ifndef::leveloffset[:leveloffset: 0]
|
||||
|
||||
:leveloffset: +1
|
||||
|
||||
include::{basedocdir}/introduction/introduction.adoc[]
|
||||
include::{basedocdir}/introduction/requirements.adoc[]
|
||||
include::{basedocdir}/introduction/new-features.adoc[]
|
||||
|
||||
:leveloffset: -1
|
||||
include::{basedocdir}/introduction/introduction.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/introduction/requirements.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/introduction/new-features.adoc[leveloffset=+1]
|
||||
|
||||
[[reference]]
|
||||
= Reference Guide
|
||||
|
||||
:leveloffset: +1
|
||||
|
||||
include::{basedocdir}/reference/introduction.adoc[]
|
||||
include::{basedocdir}/reference/bootstrap.adoc[]
|
||||
include::{basedocdir}/reference/bootstrap-annotations.adoc[]
|
||||
include::{basedocdir}/reference/data.adoc[]
|
||||
include::{basedocdir}/reference/serialization.adoc[]
|
||||
include::{basedocdir}/reference/mapping.adoc[]
|
||||
include::{basedocdir}/reference/repositories.adoc[]
|
||||
include::{basedocdir}/reference/function-annotations.adoc[]
|
||||
include::{basedocdir}/reference/lucene.adoc[]
|
||||
include::{basedocdir}/reference/gemfire-bootstrap.adoc[]
|
||||
include::{basedocdir}/reference/samples.adoc[]
|
||||
|
||||
:leveloffset: -1
|
||||
include::{basedocdir}/reference/introduction.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/bootstrap.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/bootstrap-annotations.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/data.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/serialization.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/mapping.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/repositories.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/function-annotations.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/lucene.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/gemfire-bootstrap.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/samples.adoc[leveloffset=+1]
|
||||
|
||||
[[resources]]
|
||||
= Resources
|
||||
@@ -53,22 +48,14 @@ In addition to this reference documentation, there are a number of other resourc
|
||||
how to use Pivotal GemFire with the _Spring Framework_. These additional, third-party resources are enumerated
|
||||
in this section.
|
||||
|
||||
:leveloffset: +1
|
||||
|
||||
include::{basedocdir}/links.adoc[]
|
||||
|
||||
:leveloffset: -1
|
||||
include::{basedocdir}/links.adoc[leveloffset=+1]
|
||||
|
||||
[[appendices]]
|
||||
= Appendices
|
||||
|
||||
:!sectnums:
|
||||
:leveloffset: +1
|
||||
|
||||
include::{spring-data-commons-docs}/repository-namespace-reference.adoc[]
|
||||
include::{spring-data-commons-docs}/repository-populator-namespace-reference.adoc[]
|
||||
include::{spring-data-commons-docs}/repository-query-keywords-reference.adoc[]
|
||||
include::{spring-data-commons-docs}/repository-query-return-types-reference.adoc[]
|
||||
include::{basedocdir}/appendix/appendix-schema.adoc[]
|
||||
|
||||
:leveloffset: -1
|
||||
include::{spring-data-commons-docs}/repository-namespace-reference.adoc[leveloffset=+1]
|
||||
include::{spring-data-commons-docs}/repository-populator-namespace-reference.adoc[leveloffset=+1]
|
||||
include::{spring-data-commons-docs}/repository-query-keywords-reference.adoc[leveloffset=+1]
|
||||
include::{spring-data-commons-docs}/repository-query-return-types-reference.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/appendix/appendix-schema.adoc[leveloffset=+1]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[[introduction]]
|
||||
= Introduction
|
||||
|
||||
Welcome! The _Spring Data for Pivotal GemFire_ reference guide explains how to use the _Spring Framework_
|
||||
The Spring Data for Pivotal GemFire reference guide explains how to use the Spring Framework
|
||||
to configure and develop applications with Pivotal GemFire. It presents the basic concepts and provides
|
||||
numerous examples to help you get started.
|
||||
|
||||
@@ -1,124 +1,120 @@
|
||||
[[new-features]]
|
||||
= New Features
|
||||
|
||||
NOTE: As of the 1.2.0.RELEASE, this project, formerly known as _Spring Pivotal GemFire_, has been renamed to
|
||||
_Spring Data for Pivotal GemFire_ to reflect that it is now a module of the
|
||||
NOTE: As of the 1.2.0.RELEASE, this project, formerly known as Spring Pivotal GemFire, has been renamed to
|
||||
Spring Data for Pivotal GemFire to reflect that it is now a module of the
|
||||
http://projects.spring.io/spring-data/[Spring Data] project
|
||||
and built on https://pivotal.io/pivotal-gemfire[Pivotal GemFire].
|
||||
|
||||
[[new-in-1-2-0]]
|
||||
== New in the 1.2 Release
|
||||
|
||||
* Full support for Pivotal GemFire configuration via the SDG *gfe* namespace. Now Pivotal GemFire components may be configured completely without requiring a native *cache.xml* file.
|
||||
* Full support for Pivotal GemFire configuration through the SDG *gfe* namespace. Now Pivotal GemFire components may be configured completely without requiring a native cache.xml file.
|
||||
* WAN Gateway support for Pivotal GemFire 6.6.x. See <<bootstrap:gateway>>.
|
||||
* Spring Data Repository support using a dedicated SDG namespace, *gfe-data*. See <<gemfire-repositories>>
|
||||
* Namespace support for registering Pivotal GemFire Functions. See <<bootstrap:function>>
|
||||
* A top-level `<disk-store>` element has been added to the SDG *gfe* namespace to allow sharing of persist stores among Regions,
|
||||
and other components that support persistent backup or overflow. See <<bootstrap-diskstore>>
|
||||
* A top-level `<disk-store>` element has been added to the SDG *gfe* namespace to allow sharing of persist stores among regions
|
||||
as well as other components that support persistent backup or overflow. See <<bootstrap-diskstore>>
|
||||
+
|
||||
WARNING: The `<*-region>` elements no longer allow a nested `<disk-store>` element.
|
||||
+
|
||||
* Pivotal GemFire Sub-Regions are supported via nested `<*-region>` elements.
|
||||
* Pivotal GemFire Sub-Regions are supported by nested `<*-region>` elements.
|
||||
* A `<local-region>` element has been added to configure a Local Region.
|
||||
* Support for the re-designed WAN Gateway in Pivotal GemFire 7.0.
|
||||
|
||||
[[new-in-1-3-0]]
|
||||
== New in the 1.3 Release
|
||||
|
||||
* Annotation support for Pivotal GemFire Functions. It is now possible to declare and register Functions written as POJOs using annotations. In addition, Function executions are defined as
|
||||
* Annotation support for Pivotal GemFire Functions. It is now possible to declare and register Functions written as POJOs by using annotations. In addition, function executions are defined as
|
||||
annotated interfaces, similar to the way Spring Data Repositories work. See <<function-annotations>>.
|
||||
* Added a `<datasource>` element to the SDG *gfe-data* namespace to simplify establishing a basic <<data-access:datasource,client connection>> to a Pivotal GemFire data grid.
|
||||
* Added a `<json-region-autoproxy>` element to the SDG *gfe-data* namespace to <<bootstrap:region:json,support JSON>> features introduced
|
||||
* Added a `<datasource>` element to the SDG `gfe-data` namespace to simplify establishing a basic <<data-access:datasource,client connection>> to a Pivotal GemFire data grid.
|
||||
* Added a `<json-region-autoproxy>` element to the SDG `gfe-data` namespace to <<bootstrap:region:json,support JSON>> features introduced
|
||||
in Pivotal GemFire 7.0, enabling Spring AOP to perform the necessary conversions automatically on Region operations.
|
||||
* Upgraded to Pivotal GemFire 7.0.1 and added namespace support for new AsyncEventQueue attributes.
|
||||
* Added support for setting subscription interest policy on Regions.
|
||||
* Support for void returns on Function executions. See <<function-annotations>> for complete details.
|
||||
* Support for persisting Local Regions. See <<bootstrap:region:local>> and <<bootstrap:region:common:attributes>>.
|
||||
* Support for persisting Local Regions. See <<bootstrap:region:local>>.
|
||||
* Support for entry time-to-live and entry idle-time on a Pivotal GemFire Client Cache. See <<bootstrap:cache:client>>.
|
||||
* Support for multiple Spring Data for Pivotal GemFire web-based applications using a single Pivotal GemFire cluster, operating concurrently inside tc Server.
|
||||
* Support for concurrency-checks-enabled on all Pivotal GemFire Cache Region definitions using the SDG *gfe* namespace. See <<bootstrap:region:common:attributes>>.
|
||||
* Support for Cache Loaders and Cache Writers on Client, Local Regions. See <<bootstrap:region:common:loaders-writers>>.
|
||||
* Support for registering CacheListeners, AsyncEventQueues and Gateway Senders on Pivotal GemFire Cache Sub-Regions.
|
||||
* Support for multiple Spring Data for Pivotal GemFire web-based applications by using a single Pivotal GemFire cluster, operating concurrently inside tc Server.
|
||||
* Support for `concurrency-checks-enabled` on all Pivotal GemFire Cache Region definitions by using the SDG `gfe` namespace. See <<bootstrap:region:common:attributes>>.
|
||||
* Support for Cache Loaders and Cache Writers on the Client for Local Regions.
|
||||
* Support for registering CacheListeners, AsyncEventQueues, and Gateway Senders on Pivotal GemFire Cache Sub-Regions.
|
||||
* Support for PDX persistent keys in Pivotal GemFire Regions.
|
||||
* Support for correct Partition Region bean creation in a Spring context when collocation is specified with the *colocated-with* attribute.
|
||||
* Full support for Pivotal GemFire Cache Sub-Regions using proper, nested `<*-region>` element syntax in the SDG *gfe* namespace.
|
||||
* Support for correct Partition Region bean creation in a Spring context when collocation is specified with the `colocated-with` attribute.
|
||||
* Full support for Pivotal GemFire Cache Sub-Regions using proper, nested `<*-region>` element syntax in the SDG `gfe` namespace.
|
||||
* Upgraded Spring Data for Pivotal GemFire to Spring Framework 3.2.8.
|
||||
* Upgraded Spring Data for Pivotal GemFire to Spring Data Commons 1.7.1.
|
||||
|
||||
[[new-in-1-4-0]]
|
||||
== New in the 1.4 Release
|
||||
|
||||
* Upgrades to Pivotal GemFire 7.0.2.
|
||||
* Upgrades to _Spring Data Commons_ 1.8.x.RELEASE.
|
||||
* Upgrades to _Spring Framework_ 3.2.x.RELEASE.
|
||||
* Integrates _Spring Data for Pivotal GemFire_ with _Spring Boot_, which includes both a *spring-boot-starter-data-gemfire* POM
|
||||
along with a _Spring Boot_ sample application demonstrating Pivotal GemFire Cache Transactions configured with SDG
|
||||
and bootstrapped with _Spring Boot_.
|
||||
* Support for bootstrapping a Spring `ApplicationContext` in a Pivotal GemFire Server when started from _Gfsh_.
|
||||
* Upgraded to Pivotal GemFire 7.0.2.
|
||||
* Upgraded to Spring Data Commons 1.8.x.RELEASE.
|
||||
* Upgraded to Spring Framework 3.2.x.RELEASE.
|
||||
* Integrated Spring Data for Pivotal GemFire with Spring Boot, which includes both a `spring-boot-starter-data-gemfire` POM
|
||||
and a Spring Boot sample application that demonstrates Pivotal GemFire Cache Transactions configured with SDG
|
||||
and bootstrapped with Spring Boot.
|
||||
* Added support for bootstrapping a Spring `ApplicationContext` in a Pivotal GemFire Server when started from `Gfsh`.
|
||||
See <<gemfire-bootstrap>> for more details.
|
||||
* Support for persisting application domain object/entities to multiple Pivotal GemFire Cache Regions.
|
||||
* Added support for persisting application domain object and entities to multiple Pivotal GemFire Cache Regions.
|
||||
See <<mapping.entities>> for more details.
|
||||
* Support for persisting application domain object/entities to Pivotal GemFire Cache Sub-Regions, avoiding collisions
|
||||
when Sub-Regions are uniquely identifiable, but identically named.
|
||||
* Added support for persisting application domain object and entities to Pivotal GemFire Cache Sub-Regions, avoiding collisions
|
||||
when Sub-Regions are uniquely identifiable but identically named.
|
||||
See <<mapping.entities>> for more details.
|
||||
* Adds strict XSD type rules to, and full support for, Data Policies and Region Shortcuts
|
||||
* Added strict XSD type rules to and full support for Data Policies and Region Shortcuts
|
||||
on all Pivotal GemFire Cache Region types.
|
||||
* Changed the default behavior of SDG `<*-region>` elements from lookup to always create a new Region
|
||||
along with an option to restore old behavior using the *ignore-if-exists* attribute.
|
||||
along with an option to restore the old behavior (by using the `ignore-if-exists` attribute).
|
||||
See <<bootstrap:region:common:attributes, Common Region Attributes>>
|
||||
and <<bootstrap:region:common:regions-subregions-lookups-caution>>
|
||||
for more details.
|
||||
* _Spring Data for Pivotal GemFire_ can now be fully built and ran on JDK 7 and JDK 8.
|
||||
|
||||
CAUTION: Pivotal GemFire has not yet been fully tested and certified to run JDK 8; See
|
||||
http://gemfire.docs.pivotal.io/docs-gemfire/supported_configs/supported_configs_and_system_reqs.html[Pivotal GemFire User Guide]
|
||||
for additional details.
|
||||
* Spring Data for Pivotal GemFire can now be fully built and ran on JDK 7 and JDK 8.
|
||||
|
||||
[[new-in-1-5-0]]
|
||||
== New in the 1.5 Release
|
||||
|
||||
* Maintains support for Pivotal GemFire 7.0.2.
|
||||
* Upgrades to _Spring Data Commons_ 1.9.x.RELEASE.
|
||||
* Upgrades to _Spring Framework_ 4.0.x.RELEASE.
|
||||
* Reference Guide migrated to Asciidoc.
|
||||
* Renewed support for deploying _Spring Data for Pivotal GemFire_ in an OSGi container.
|
||||
* Removed all default values in the _Spring Data for Pivotal GemFire_ XML namespace Region-type elements to
|
||||
* Maintained support for Pivotal GemFire 7.0.2.
|
||||
* Upgraded to _Spring Data Commons_ 1.9.x.RELEASE.
|
||||
* Upgraded to _Spring Framework_ 4.0.x.RELEASE.
|
||||
* Migrated the Reference Guide to Asciidoc.
|
||||
* Renewed support for deploying Spring Data for Pivotal GemFire in an OSGi container.
|
||||
* Removed all default values in the Spring Data for Pivotal GemFire XML namespace Region-type elements to
|
||||
rely on Pivotal GemFire defaults instead.
|
||||
* Added convenience to automatically create Disk Store directory locations.
|
||||
* SDG annotated Function implementations can now be executed from _Gfsh_.
|
||||
* Enable Pivotal GemFire `GatewayReceivers` to be started manually.
|
||||
* Support for Auto Region Lookups. See <<bootstrap:region:auto-lookup>> for further details.
|
||||
* Support for Region Templates. See <<bootstrap:region:common:region-templates>> for further details.
|
||||
* SDG annotated Function implementations can now be executed from `Gfsh`.
|
||||
* Enabled Pivotal GemFire `GatewayReceivers` to be started manually.
|
||||
* Added support for Auto Region Lookups. See <<bootstrap:region:auto-lookup>> for further details.
|
||||
* Added support for Region Templates. See <<bootstrap:region:common:region-templates>> for further details.
|
||||
|
||||
[[new-in-1-6-0]]
|
||||
== New in the 1.6 Release
|
||||
|
||||
* Upgrades to Pivotal GemFire 8.0.0.
|
||||
* Upgrades to _Spring Data Commons_ 1.10.x.RELEASE.
|
||||
* Maintains support on _Spring Framework_ 4.0.x.RELEASE.
|
||||
* Adds support for Pivotal GemFire 8's new Cluster-based Configuration.
|
||||
* Enables 'auto-reconnect' functionality to be employed in Spring-configured Pivotal GemFire Servers.
|
||||
* Allows the creation of concurrent and parallel Async Event Queues and Gateway Senders.
|
||||
* Adds support for Pivotal GemFire 8's Region data compression.
|
||||
* Adds attributes to set both critical and warning percentages on Disk Store usage.
|
||||
* Supports the capability to add the new EventSubstitutionFilters to GatewaySenders.
|
||||
* Upgraded to Pivotal GemFire 8.0.0.
|
||||
* Upgraded to Spring Data Commons 1.10.x.RELEASE.
|
||||
* Maintained support for Spring Framework 4.0.x.RELEASE.
|
||||
* Added support for Pivotal GemFire 8's new Cluster-based Configuration.
|
||||
* Enabled 'auto-reconnect' functionality to be employed in Spring-configured Pivotal GemFire Servers.
|
||||
* Allowed the creation of concurrent and parallel Async Event Queues and Gateway Senders.
|
||||
* Added support for Pivotal GemFire 8's Region data compression.
|
||||
* Added attributes to set both critical and warning percentages on Disk Store usage.
|
||||
* Supported the capability to add the new EventSubstitutionFilters to GatewaySenders.
|
||||
|
||||
[[new-in-1-7-0]]
|
||||
== New in the 1.7 Release
|
||||
|
||||
* Upgrades to Pivotal GemFire 8.1.0.
|
||||
* Upgrades to _Spring Data Commons_ 1.11.x.RELEASE.
|
||||
* Upgrades to _Spring Framework_ 4.1.x.RELEASE.
|
||||
* Early access support for Pivotal GemFire.
|
||||
* Support for adding _Spring_-defined Cache Listeners, Loaders and Writers on "existing" Pivotal GemFire Regions
|
||||
configured in _Spring_ XML, `cache.xml` or even with Pivotal GemFire's _Cluster Config_.
|
||||
* _Spring_ JavaConfig support added to `SpringContextBootstrappingInitializer`.
|
||||
* Support for custom `ClassLoaders` in `SpringContextBootstrappingInitializer` to load _Spring_-defined bean classes.
|
||||
* Support for `LazyWiringDeclarableSupport` re-initialization and complete replacement for `WiringDeclarableSupport`.
|
||||
* Adds `locators` and `servers` attributes to the `<gfe:pool>` element allowing variable Locator/Server
|
||||
endpoint lists configured with _Spring's_ property placeholders.
|
||||
* Enables the use of `<gfe-data:datasource>` element with non-_Spring_ configured Pivotal GemFire Servers.
|
||||
* Multi-Index definition and creation support.
|
||||
* Upgraded to Pivotal GemFire 8.1.0.
|
||||
* Upgraded to Spring Data Commons 1.11.x.RELEASE.
|
||||
* Upgraded to Spring Framework 4.1.x.RELEASE.
|
||||
* Added early access support for Pivotal GemFire.
|
||||
* Added support for adding Spring-defined Cache Listeners, Loaders, and Writers on "existing" Pivotal GemFire Regions
|
||||
configured in Spring XML, `cache.xml`, or even with Pivotal GemFire's Cluster Config.
|
||||
* Added Spring JavaConfig support to `SpringContextBootstrappingInitializer`.
|
||||
* Added support for custom `ClassLoaders` in `SpringContextBootstrappingInitializer` to load Spring-defined bean classes.
|
||||
* Added support for `LazyWiringDeclarableSupport` re-initialization and complete replacement for `WiringDeclarableSupport`.
|
||||
* Added `locators` and `servers` attributes to the `<gfe:pool>` element, allowing variable Locator and Server
|
||||
endpoint lists configured with Spring's property placeholders.
|
||||
* Enables the use of the `<gfe-data:datasource>` element with non-Spring-configured Pivotal GemFire Servers.
|
||||
* Added multi-index definition and creation support.
|
||||
* <<bootstrap:region:expiration:annotation>>
|
||||
* <<gemfire-repositories:oql-extensions>>
|
||||
* <<bootstrap:snapshot>>
|
||||
@@ -126,50 +122,50 @@ endpoint lists configured with _Spring's_ property placeholders.
|
||||
[[new-in-1-8-0]]
|
||||
== New in the 1.8 Release
|
||||
|
||||
* Upgrades to Pivotal GemFire 8.2.0.
|
||||
* Upgrades to _Spring Data Commons_ 1.12.x.RELEASE.
|
||||
* Upgrades to _Spring Framework_ 4.2.x.RELEASE.
|
||||
* Adds Maven POM to build SDG with Maven.
|
||||
* Adds support for CDI.
|
||||
* Enables a `ClientCache` to be configured without a `Pool`.
|
||||
* `<gfe:cache>` and `<gfe:client-cache>` elements `use-bean-factory-locator` attributes now default to *false*.
|
||||
* Adds `durable-client-id` and `durable-client-timeout` attributes to `<gfe:client-cache>`.
|
||||
* GemfirePersistentProperty now properly handles other non-entity, scalar-like types (e.g. `BigDecimal`, `BigInteger`).
|
||||
* Prevents SDG-defined `Pools` from being destroyed before `Regions` that use those `Pools`.
|
||||
* Handles case-insensitive Pivotal GemFire OQL queries defined as _Repository_ query methods.
|
||||
* Changes `Pivotal GemFireCache.evict(key)` to call `Region.remove(key)` in SDG's _Spring Cache Abstraction_ support.
|
||||
* Fixes `RegionNotFoundException` with _Repository_ queries on a client `Region` associated with a specific `Pool`
|
||||
* Upgraded to Pivotal GemFire 8.2.0.
|
||||
* Upgraded to Spring Data Commons 1.12.x.RELEASE.
|
||||
* Upgraded to Spring Framework 4.2.x.RELEASE.
|
||||
* Added Maven POM to build SDG with Maven.
|
||||
* Addsed support for CDI.
|
||||
* Enabled a `ClientCache` to be configured without a `Pool`.
|
||||
* Made `<gfe:cache>` and `<gfe:client-cache>` elements `use-bean-factory-locator` attributes default to *false*.
|
||||
* Added `durable-client-id` and `durable-client-timeout` attributes to `<gfe:client-cache>`.
|
||||
* Made GemfirePersistentProperty now properly handle other non-entity, scalar-like types (such as `BigDecimal` and `BigInteger`).
|
||||
* Prevented SDG-defined `Pools` from being destroyed before `Regions` that use those `Pools`.
|
||||
* Handled case-insensitive Pivotal GemFire OQL queries defined as Repository query methods.
|
||||
* Changed `Pivotal GemFireCache.evict(key)` to call `Region.remove(key)` in SDG's Spring Cache Abstraction support.
|
||||
* Fixed `RegionNotFoundException` with Repository queries on a client `Region` associated with a specific `Pool`
|
||||
configured for Pivotal GemFire server groups.
|
||||
* Changes `Gateway Senders/Receivers` to no longer be tied to the _Spring_ container.
|
||||
* Changed `Gateway Senders/Receivers` to no longer be tied to the _Spring_ container.
|
||||
|
||||
[[new-in-1-9-0]]
|
||||
== New in the 1.9 Release
|
||||
|
||||
* Upgrades to Pivotal GemFire 8.2.4.
|
||||
* Upgrades to _Spring Data Commons_ 1.13.x.RELEASE.
|
||||
* Upgrades to _Spring Framework_ 4.3.x.RELEASE.
|
||||
* Introduces an entirely new Annotation-based configuration model inspired by _Spring Boot_.
|
||||
* Adds support for suspend and resume in the `GemfireTransactionManager`.
|
||||
* Adds support in _Repositories_ to use the bean `id` property as the Region key when the `@Id` annotation
|
||||
* Upgraded to Pivotal GemFire 8.2.4.
|
||||
* Upgraded to Spring Data Commons 1.13.x.RELEASE.
|
||||
* Upgraded to Spring Framework 4.3.x.RELEASE.
|
||||
* Introduced an entirely new Annotation-based configuration model inspired by Spring Boot.
|
||||
* Added support for suspend and resume in the `GemfireTransactionManager`.
|
||||
* Added support in Repositories to use the bean `id` property as the Region key when the `@Id` annotation
|
||||
is not present.
|
||||
* Uses `MappingPdxSerializer` as the default Pivotal GemFire serialization strategy when `@EnablePdx` is used.
|
||||
* Enables `GemfireCacheManager` to explicitly list Region names to be used in the _Spring's Caching Abstraction_.
|
||||
* Configure Pivotal GemFire Caches, CacheServers, Locators, Pools, Regions, Indexes, DiskStores, Expiration, Eviction,
|
||||
* Used `MappingPdxSerializer` as the default Pivotal GemFire serialization strategy when `@EnablePdx` is used.
|
||||
* Enabled `GemfireCacheManager` to explicitly list Region names to be used in the Spring's Caching Abstraction.
|
||||
* Configured Pivotal GemFire Caches, CacheServers, Locators, Pools, Regions, Indexes, DiskStores, Expiration, Eviction,
|
||||
Statistics, Mcast, HttpService, Auth, SSL, Logging, System Properties.
|
||||
* Repository support with multiple _Spring Data_ modules on the classpath.
|
||||
* Added repository support with multiple Spring Data modules on the classpath.
|
||||
|
||||
[[new-in-2-0-0]]
|
||||
== New in the 2.0 Release
|
||||
|
||||
* Upgrades to Pivotal GemFire 9.0.x.
|
||||
* Upgrades to _Spring Data Commons_ 2.0.x.RELEASE.
|
||||
* Upgrades to _Spring Framework_ 5.0.x.RELEASE.
|
||||
* Reorganizes the SDG codebase by better packaging different classes and components by concern.
|
||||
* Adds extensive support for Java 8 types, particularly in the SD _Repository_ abstraction.
|
||||
* Changes to the _Repository_ interface and abstraction, e.g. IDs are no longer required to be `java.io.Serializable`.
|
||||
* Sets `@EnableEntityDefinedRegions` annotation `ignoreIfExists` attribute to *true* by default.
|
||||
* Sets `@Indexed` annotation `override` attribute to *false* by default.
|
||||
* Renames `@EnableIndexes` to `@EnableIndexing`.
|
||||
* Introduces a `InterestsBuilder` class to easily and conveniently express Interests in keys/values between client
|
||||
* Upgraded to Pivotal GemFire 9.0.x.
|
||||
* Upgraded to Spring Data Commons 2.0.x.RELEASE.
|
||||
* Upgraded to Spring Framework 5.0.x.RELEASE.
|
||||
* Reorganized the SDG codebase by better packaging different classes and components by concern.
|
||||
* Added extensive support for Java 8 types, particularly in the SD Repository abstraction.
|
||||
* Changed to the Repository interface and abstraction, e.g. IDs are no longer required to be `java.io.Serializable`.
|
||||
* Set `@EnableEntityDefinedRegions` annotation `ignoreIfExists` attribute to `true` by default.
|
||||
* Set `@Indexed` annotation `override` attribute to `false` by default.
|
||||
* Renamed `@EnableIndexes` to `@EnableIndexing`.
|
||||
* Introduced a `InterestsBuilder` class to easily and conveniently express Interests in keys and values between client
|
||||
and server when using JavaConfig.
|
||||
* Adds support for Off-Heap, Redis Adapter and Pivotal GemFire's new Security framework to the Annotation configuration model.
|
||||
* Added support for Off-Heap, Redis Adapter, and Pivotal GemFire's new Security framework to the Annotation configuration model.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[[requirements]]
|
||||
= Requirements
|
||||
|
||||
_Spring Data for Pivotal GemFire_ requires JDK 8.0, http://projects.spring.io/spring-framework[Spring Framework] 5
|
||||
Spring Data for Pivotal GemFire requires JDK 8.0, http://projects.spring.io/spring-framework[Spring Framework] 5
|
||||
and http://geode.apache.org/[Pivotal GemFire] 9.0.x.
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
= Preface
|
||||
|
||||
_Spring Data for Pivotal GemFire_ focuses on integrating the _Spring Framework's_ powerful, non-invasive programming model
|
||||
and concepts with Pivotal GemFire to simplify configuration and development of Java applications using Pivotal GemFire.
|
||||
Spring Data for Pivotal GemFire focuses on integrating the Spring Framework's powerful, non-invasive programming model
|
||||
and concepts with Pivotal GemFire to simplify configuration and development of Java applications when you use Pivotal GemFire.
|
||||
|
||||
This document assumes the reader already has a basic understanding and some familiarity with the core _Spring Framework_
|
||||
This document assumes you already have a basic understanding of and some familiarity with the core Spring Framework
|
||||
and Pivotal GemFire concepts and APIs.
|
||||
|
||||
While every effort has been made to ensure this documentation is comprehensive and complete without errors,
|
||||
some topics are beyond the scope of this document and may require more explanation (e.g. data distribution management
|
||||
using partitioning with HA while still preserving consistency). Additionally, some typos might have crept in.
|
||||
If you do spot mistakes or even more serious errors and you can spare a few cycles, please do bring these issues
|
||||
to the attention of the _Spring Data_ team by raising an appropriate
|
||||
some topics are beyond the scope of this document and may require more explanation (for example, data distribution management
|
||||
using partitioning with HA while still preserving consistency). Additionally, some typographical errors might have crept in.
|
||||
If you do spot mistakes or even more serious errors, please bring these issues
|
||||
to the attention of the Spring Data team by raising an appropriate
|
||||
https://jira.spring.io/browse/SGF[issue in JIRA].
|
||||
|
||||
Thank you.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,48 +1,48 @@
|
||||
[[bootstrap]]
|
||||
= Bootstrapping Pivotal GemFire with the Spring container
|
||||
|
||||
_Spring Data for Pivotal GemFire_ provides full configuration and initialization of the Pivotal GemFire In-Memory Data Grid (IMDG)
|
||||
using the _Spring_ IoC container. The framework includes several classes to help simplify the configuration of
|
||||
Pivotal GemFire components including: Caches, Regions, Indexes, DiskStores, Functions, WAN Gateways, persistence backup
|
||||
along with several other Distributed System components in order to support a variety of use cases with minimal effort.
|
||||
Spring Data for Pivotal GemFire provides full configuration and initialization of the Pivotal GemFire In-Memory Data Grid (IMDG)
|
||||
by using the Spring IoC container. The framework includes several classes to help simplify the configuration of
|
||||
Pivotal GemFire components, including: Caches, Regions, Indexes, DiskStores, Functions, WAN Gateways, persistence backup,
|
||||
and several other Distributed System components to support a variety of use cases with minimal effort.
|
||||
|
||||
NOTE: This section assumes basic familiarity with Pivotal GemFire. For more information,
|
||||
see the Pivotal GemFire http://geode.apache.org/docs/[product documentation].
|
||||
|
||||
[[bootstrap:namespace:xml]]
|
||||
== Advantages of using Spring over Pivotal GemFire `cache.xml`
|
||||
== Advantages of Using Spring over Pivotal GemFire `cache.xml`
|
||||
|
||||
_Spring Data for Pivotal GemFire's_ XML namespace supports full configuration of the Pivotal GemFire In-Memory Data Grid (IMDG).
|
||||
The XML namespace is the preferred way to configure Pivotal GemFire in a _Spring_ context in order to properly
|
||||
manage Pivotal GemFire's lifecycle inside the _Spring_ container. While support for Pivotal GemFire's native `cache.xml` persists
|
||||
for legacy reasons, Pivotal GemFire application developers are encouraged to do everything in _Spring_ XML to take advantage of
|
||||
the many wonderful things _Spring_ has to offer such as modular XML configuration, property placeholders and overrides,
|
||||
SpEL, and environment profiles. Behind the XML namespace, _Spring Data for Pivotal GemFire_ makes extensive use of _Spring's_
|
||||
`FactoryBean` pattern to simplify the creation, configuration and initialization of Pivotal GemFire components.
|
||||
Spring Data for Pivotal GemFire's XML namespace supports full configuration of the Pivotal GemFire In-Memory Data Grid (IMDG).
|
||||
The XML namespace is one of two ways to configure Pivotal GemFire in a Spring context in order to properly
|
||||
manage Pivotal GemFire's lifecycle inside the Spring container. The other way to configure Pivotal Gemfire in a Spring context is by using <<bootstrap-annotation-config,annotation-based configuration>>. While support for Pivotal GemFire's native `cache.xml` persists
|
||||
for legacy reasons, Pivotal GemFire application developers who use XML configuration are encouraged to do everything in Spring XML to take advantage of
|
||||
the many wonderful things Spring has to offer, such as modular XML configuration, property placeholders and overrides,
|
||||
SpEL (https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#expressions[Spring Expression Language]), and environment profiles. Behind the XML namespace, Spring Data for Pivotal GemFire makes extensive use of Spring's
|
||||
`FactoryBean` pattern to simplify the creation, configuration, and initialization of Pivotal GemFire components.
|
||||
|
||||
Pivotal GemFire provides several callback interfaces, such as `CacheListener`, `CacheLoader` and `CacheWriter`,
|
||||
that allow developers to add custom event handlers. Using _Spring's_ IoC container, these callbacks may be configured
|
||||
as normal _Spring_ beans and injected into Pivotal GemFire components. This is a significant improvement over native `cache.xml`,
|
||||
Pivotal GemFire provides several callback interfaces, such as `CacheListener`, `CacheLoader`, and `CacheWriter`,
|
||||
that let developers add custom event handlers. Using Spring's IoC container, you can configure these callbacks
|
||||
as normal Spring beans and inject them into Pivotal GemFire components. This is a significant improvement over native `cache.xml`,
|
||||
which provides relatively limited configuration options and requires callbacks to implement Pivotal GemFire's `Declarable`
|
||||
interface (see <<apis:declarable>> to see how you can still use `Declarables` within _Spring's_ IoC/DI container).
|
||||
interface (see <<apis:declarable>> to see how you can still use `Declarables` within Spring's IoC/DI container).
|
||||
|
||||
In addition, IDEs, such as the _Spring Tool Suite_ (STS), provide excellent support for _Spring_ XML namespaces
|
||||
including code completion, pop-up annotations, and real time validation, making them easy to use.
|
||||
In addition, IDEs, such as the Spring Tool Suite (STS), provide excellent support for Spring XML namespaces,
|
||||
including code completion, pop-up annotations, and real-time validation.
|
||||
|
||||
[[bootstrap:namespace]]
|
||||
== Using the Core Namespace
|
||||
|
||||
To simplify configuration, _Spring Data for Pivotal GemFire_ provides a dedicated XML namespace for configuring core Pivotal GemFire
|
||||
components. It is possible to configure beans directly using _Spring's_ standard `<bean>` definition. However,
|
||||
all bean properties are exposed via the XML namespace so there is little benefit to using raw bean definitions.
|
||||
For more information about XML Schema-based configuration in _Spring_, see the
|
||||
To simplify configuration, Spring Data for Pivotal GemFire provides a dedicated XML namespace for configuring core Pivotal GemFire
|
||||
components. It is possible to configure beans directly by using Spring's standard `<bean>` definition. However,
|
||||
all bean properties are exposed through the XML namespace, so there is little benefit to using raw bean definitions.
|
||||
For more information about XML Schema-based configuration in Spring, see the
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config[appendix]
|
||||
in the _Spring Framework_ reference documentation.
|
||||
in the Spring Framework reference documentation.
|
||||
|
||||
NOTE: _Spring Data Repository_ support uses a separate XML namespace. See <<gemfire-repositories>> for more information
|
||||
on how to configure _Spring Data for Pivotal GemFire_ Repositories.
|
||||
NOTE: Spring Data Repository support uses a separate XML namespace. See <<gemfire-repositories>> for more information
|
||||
on how to configure Spring Data for Pivotal GemFire Repositories.
|
||||
|
||||
To use the _Spring Data for Pivotal GemFire_ XML namespace, simply declare it in your _Spring_ XML configuration meta-data:
|
||||
To use the Spring Data for Pivotal GemFire XML namespace, declare it in your Spring XML configuration meta-data, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -60,18 +60,18 @@ To use the _Spring Data for Pivotal GemFire_ XML namespace, simply declare it in
|
||||
|
||||
</beans>
|
||||
----
|
||||
<1> _Spring Data for Pivotal GemFire_ XML namespace prefix. Any name will do but through out this reference documentation,
|
||||
`gfe` will be used.
|
||||
<1> Spring Data for Pivotal GemFire XML namespace prefix. Any name works, but, throughout this reference documentation,
|
||||
`gfe` is used.
|
||||
<2> The XML namespace prefix is mapped to the URI.
|
||||
<3> The XML namespace URI location. Note that even though the location points to an external address (which does exist
|
||||
and is valid), _Spring_ will resolve the schema locally as it is included in the _Spring Data for Pivotal GemFire_ library.
|
||||
<3> The XML namespace URI location. Note that, even though the location points to an external address (which does exist
|
||||
and is valid), Spring resolves the schema locally, as it is included in the Spring Data for Pivotal GemFire library.
|
||||
<4> Example declaration using the XML namespace with the `gfe` prefix.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
It is possible to change the default namespace from `beans` to `gfe`. This is useful for XML configuration
|
||||
composed mainly of Pivotal GemFire components as it avoids declaring the prefix. To achieve this, simply swap the namespace
|
||||
prefix declaration above:
|
||||
You can change the default namespace from `beans` to `gfe`. This is useful for XML configuration
|
||||
composed mainly of Pivotal GemFire components, as it avoids declaring the prefix. To do so, swap the namespace
|
||||
prefix declaration shown earlier, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -89,21 +89,17 @@ prefix declaration above:
|
||||
|
||||
</beans>
|
||||
----
|
||||
<1> The default namespace declaration for this XML document points to the _Spring Data for Pivotal GemFire_ XML namespace.
|
||||
<2> The `beans` namespace prefix declaration for _Spring's_ raw bean definitions.
|
||||
<1> The default namespace declaration for this XML document points to the Spring Data for Pivotal GemFire XML namespace.
|
||||
<2> The `beans` namespace prefix declaration for Spring's raw bean definitions.
|
||||
<3> Bean declaration using the `beans` namespace. Notice the prefix.
|
||||
<4> Bean declaration using the `gfe` namespace. Notice the lack of prefix since `gfe` is the default namespace.
|
||||
====
|
||||
|
||||
:leveloffset: +1
|
||||
|
||||
include::{basedocdir}/reference/data-access.adoc[]
|
||||
include::{basedocdir}/reference/cache.adoc[]
|
||||
include::{basedocdir}/reference/region.adoc[]
|
||||
include::{basedocdir}/reference/indexing.adoc[]
|
||||
include::{basedocdir}/reference/diskstore.adoc[]
|
||||
include::{basedocdir}/reference/snapshot.adoc[]
|
||||
include::{basedocdir}/reference/function.adoc[]
|
||||
include::{basedocdir}/reference/gateway.adoc[]
|
||||
|
||||
:leveloffset: -1
|
||||
include::{basedocdir}/reference/data-access.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/cache.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/region.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/indexing.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/diskstore.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/snapshot.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/function.adoc[leveloffset=+1]
|
||||
include::{basedocdir}/reference/gateway.adoc[v]
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
[[bootstrap:cache]]
|
||||
= Configuring a Cache
|
||||
|
||||
To use Pivotal GemFire, a developer needs to either create a new `Cache` or connect to an existing one.
|
||||
With the current version of Pivotal GemFire, there can be only one open Cache per VM (technically, per `ClassLoader`).
|
||||
To use Pivotal GemFire, you need to either create a new `Cache` or connect to an existing one.
|
||||
With the current version of Pivotal GemFire, you can have only one open Cache per VM (more strictly, per `ClassLoader`).
|
||||
In most cases, the `Cache` should only be created once.
|
||||
|
||||
NOTE: This section describes the creation and configuration of a peer cache member, appropriate in
|
||||
peer-to-peer (P2P) topologies and cache servers. A cache member can also be used in standalone applications
|
||||
and integration tests. However, in most typical production systems, most application processes will act as
|
||||
cache clients, creating a `ClientCache` instance instead. This is described in the sections <<bootstrap:cache:client>>
|
||||
and <<bootstrap:region:client>>.
|
||||
peer-to-peer (P2P) topologies and cache servers. A cache member can also be used in stand-alone applications
|
||||
and integration tests. However, in most typical production systems, most application processes act as
|
||||
cache clients, creating a `ClientCache` instance instead. This is described in the <<bootstrap:cache:client>>
|
||||
and <<bootstrap:region:client>> sections.
|
||||
|
||||
A peer cache with default configuration can be created with a very simple declaration:
|
||||
A peer cache with default configuration can be created with the following simple declaration:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:cache/>
|
||||
----
|
||||
|
||||
During Spring container initialization, any application context containing this cache definition will register
|
||||
a `CacheFactoryBean` that creates a Spring bean named `gemfireCache` referencing a Pivotal GemFire `Cache` instance.
|
||||
This bean will refer to either an existing cache, or if one does not already exist, a newly created one. Since no
|
||||
additional properties were specified, a newly created cache will apply the default cache configuration.
|
||||
During Spring container initialization, any application context containing this cache definition registers
|
||||
a `CacheFactoryBean` that creates a Spring bean named `gemfireCache`, which references a Pivotal GemFire `Cache` instance.
|
||||
This bean refers to either an existing cache or, if one does not already exist, a newly created one. Since no
|
||||
additional properties were specified, a newly created cache applies the default cache configuration.
|
||||
|
||||
All _Spring Data for Pivotal GemFire_ components that depend on the cache respect this naming convention, so there is no need
|
||||
to explicitly declare the cache dependency. If you prefer, you can make the dependency explicit via the `cache-ref`
|
||||
attribute provided by various SDG XML namespace elements. Also, you can easily override the cache's bean name using
|
||||
the `id` attribute:
|
||||
All Spring Data for Pivotal GemFire components that depend on the cache respect this naming convention, so you need not
|
||||
explicitly declare the cache dependency. If you prefer, you can make the dependency explicit by using the `cache-ref`
|
||||
attribute provided by various SDG XML namespace elements. Also, you can override the cache's bean name using
|
||||
the `id` attribute, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:cache id="myCache"/>
|
||||
----
|
||||
|
||||
A Pivotal GemFire `Cache` can be fully configured using Spring, however, Pivotal GemFire's native XML configuration file, `cache.xml`,
|
||||
is also supported. For situations where the Pivotal GemFire cache needs to be configured natively, simply provide a reference
|
||||
to the Pivotal GemFire XML configuration file using the `cache-xml-location` attribute:
|
||||
A Pivotal GemFire `Cache` can be fully configured using Spring. However, Pivotal GemFire's native XML configuration file, `cache.xml`,
|
||||
is also supported. For situations where the Pivotal GemFire cache needs to be configured natively, you can provide a reference
|
||||
to the Pivotal GemFire XML configuration file by using the `cache-xml-location` attribute, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:cache id="cacheConfiguredWithNativeXml" cache-xml-location="classpath:cache.xml"/>
|
||||
----
|
||||
|
||||
In this example, if a cache needs to be created, it will use a file named `cache.xml` located in the classpath root
|
||||
In this example, if a cache needs to be created, it uses a file named `cache.xml` located in the classpath root
|
||||
to configure it.
|
||||
|
||||
NOTE: The configuration makes use of Spring's http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#resources[`Resource`]
|
||||
abstraction to locate the file. This allows various search patterns to be used, depending on the runtime environment
|
||||
abstraction to locate the file. The `Resource` abstraction lets various search patterns be used, depending on the runtime environment
|
||||
or the prefix specified (if any) in the resource location.
|
||||
|
||||
In addition to referencing an external XML configuration file, a developer may also specify Pivotal GemFire System
|
||||
In addition to referencing an external XML configuration file, you can also specify Pivotal GemFire System
|
||||
http://geode.apache.org/docs/guide/11/reference/topics/gemfire_properties.html[properties]
|
||||
using any of Spring's `Properties` support features.
|
||||
that use any of Spring's `Properties` support features.
|
||||
|
||||
For example, the developer may use the `properties` element defined in the `util` namespace to define `Properties`
|
||||
directly or load properties from a properties file:
|
||||
For example, you can use the `properties` element defined in the `util` namespace to define `Properties`
|
||||
directly or load properties from a properties file, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -75,17 +75,17 @@ directly or load properties from a properties file:
|
||||
</beans>
|
||||
----
|
||||
|
||||
Using a properties file is recommended for externalizing environment specific settings outside
|
||||
Using a properties file is recommended for externalizing environment-specific settings outside
|
||||
the application configuration.
|
||||
|
||||
NOTE: Cache settings apply only if a new cache needs to be created. If an open cache already exists in the VM,
|
||||
NOTE: Cache settings apply only when a new cache needs to be created. If an open cache already exists in the VM,
|
||||
these settings are ignored.
|
||||
|
||||
[[bootstrap:cache:advanced]]
|
||||
== Advanced Cache Configuration
|
||||
|
||||
For advanced cache configuration, the `cache` element provides a number of configuration options exposed as attributes
|
||||
or child elements:
|
||||
or child elements, as the following listing shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -126,86 +126,86 @@ or child elements:
|
||||
</gfe:cache>
|
||||
----
|
||||
|
||||
<1> Various cache options are supported by attributes. For further information regarding anything shown in this example,
|
||||
please consult the Pivotal GemFire http://docs.pivotal.io/gemfire[product documentation].
|
||||
<1> Attributes support various cache options. For further information regarding anything shown in this example,
|
||||
see the Pivotal GemFire http://docs.pivotal.io/gemfire[product documentation].
|
||||
The `close` attribute determines whether the cache should be closed when the Spring application context is closed.
|
||||
The default is `true`, however, for use cases in which multiple application contexts use the cache
|
||||
The default is `true`. However, for use cases in which multiple application contexts use the cache
|
||||
(common in web applications), set this value to `false`.
|
||||
<2> Setting the `enable-auto-reconnect` attribute to true (default is false), allows a disconnected Pivotal GemFire member to
|
||||
<2> Setting the `enable-auto-reconnect` attribute to `true` (the default is `false`) lets a disconnected Pivotal GemFire member
|
||||
automatically reconnect and rejoin the Pivotal GemFire cluster.
|
||||
See the Pivotal GemFire http://geode.apache.org/docs/guide/11/managing/autoreconnect/member-reconnect.html[product documentation]
|
||||
for more details.
|
||||
<3> Setting the `use-bean-factory-locator` attribute to `true` (defaults to `false`) is only applicable when both
|
||||
Spring (XML) configuration meta-data and Pivotal GemFire `cache.xml` is used to configure the Pivotal GemFire cache node
|
||||
(whether client or peer). This option allows Pivotal GemFire components (e.g. `CacheLoader`) expressed in `cache.xml`
|
||||
to be auto-wired with beans (e.g. `DataSource`) defined in the Spring application context. This option is typically
|
||||
<3> Setting the `use-bean-factory-locator` attribute to `true` (it defaults to `false`) applies only when both
|
||||
Spring (XML) configuration metadata and Pivotal GemFire `cache.xml` is used to configure the Pivotal GemFire cache node
|
||||
(whether client or peer). This option lets Pivotal GemFire components (such as `CacheLoader`) expressed in `cache.xml`
|
||||
be auto-wired with beans (such as `DataSource`) defined in the Spring application context. This option is typically
|
||||
used in conjunction with `cache-xml-location`.
|
||||
<4> Setting the `use-cluster-configuration` attribute to `true` (default is `false`) enables a Pivotal GemFire member to
|
||||
<4> Setting the `use-cluster-configuration` attribute to `true` (the default is `false`) enables a Pivotal GemFire member to
|
||||
retrieve the common, shared Cluster-based configuration from a Locator.
|
||||
See the Pivotal GemFire http://geode.apache.org/docs/guide/11/configuring/cluster_config/gfsh_persist.html[product documentation]
|
||||
for more details.
|
||||
<5> Example of a `TransactionListener` callback declaration using a bean reference. The referenced bean must implement
|
||||
<5> Example of a `TransactionListener` callback declaration that uses a bean reference. The referenced bean must implement
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/TransactionListener.html[TransactionListener].
|
||||
A `TransactionListener` can be implemented to handle transaction related events (e.g. afterCommit, afterRollback).
|
||||
A `TransactionListener` can be implemented to handle transaction related events (such as afterCommit and afterRollback).
|
||||
<6> Example of a `TransactionWriter` callback declaration using an inner bean declaration. The bean must implement
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/TransactionWriter.html[TransactionWriter].
|
||||
The `TransactionWriter` is a callback that is allowed to veto a transaction.
|
||||
The `TransactionWriter` is a callback that can veto a transaction.
|
||||
<7> Example of a `GatewayConflictResolver` callback declaration using a bean reference. The referenced bean
|
||||
must implement http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/util/GatewayConflictResolver.html
|
||||
[GatewayConflictResolver].
|
||||
A `GatewayConflictResolver` is a Cache-level plugin that is called upon to decide what to do with events that originate
|
||||
A `GatewayConflictResolver` is a cache-level plugin that is called upon to decide what to do with events that originate
|
||||
in other systems and arrive through the WAN Gateway.
|
||||
<8> Enable Pivotal GemFire's http://geode.apache.org/docs/guide/11/developing/region_options/dynamic_region_creation.html[DynamicRegionFactory],
|
||||
<8> Enables Pivotal GemFire's http://geode.apache.org/docs/guide/11/developing/region_options/dynamic_region_creation.html[DynamicRegionFactory],
|
||||
which provides a distributed Region creation service.
|
||||
<9> Declares a JNDI binding to enlist an external DataSource in a Pivotal GemFire transaction.
|
||||
|
||||
[[bootstrap:cache:pdx-serialization]]
|
||||
=== Enabling PDX Serialization
|
||||
|
||||
The example above includes a number of attributes related to Pivotal GemFire's enhanced serialization framework, PDX.
|
||||
The preceding example includes a number of attributes related to Pivotal GemFire's enhanced serialization framework, PDX.
|
||||
While a complete discussion of PDX is beyond the scope of this reference guide, it is important to note that PDX
|
||||
is enabled by registering a `PdxSerializer` which is specified via the `pdx-serializer` attribute. Pivotal GemFire provides
|
||||
an implementing class `org.apache.geode.pdx.ReflectionBasedAutoSerializer` that uses Java Reflection, however, it is
|
||||
is enabled by registering a `PdxSerializer`, which is specified by setting the `pdx-serializer` attribute. Pivotal GemFire provides
|
||||
an implementing class (`org.apache.geode.pdx.ReflectionBasedAutoSerializer`) that uses Java Reflection. However, it is
|
||||
common for developers to provide their own implementation. The value of the attribute is simply a reference to
|
||||
a Spring bean that implements the `PdxSerializer` interface.
|
||||
|
||||
More information on serialization support can be found in <<serialization>>
|
||||
|
||||
[[boostrap:cache:auto-reconnect]]
|
||||
=== Enabling auto-reconnect
|
||||
=== Enabling Auto-reconnect
|
||||
|
||||
Setting the `<gfe:cache enable-auto-reconnect="[true|false*]>` attribute to `true` should be done with care.
|
||||
You should be careful when setting the `<gfe:cache enable-auto-reconnect="[true|false*]>` attribute to `true`.
|
||||
|
||||
Generally, 'auto-reconnect' should only be enabled in cases where _Spring Data for Pivotal GemFire's_ XML namespace is used to
|
||||
Generally, 'auto-reconnect' should only be enabled in cases where Spring Data for Pivotal GemFire's XML namespace is used to
|
||||
configure and bootstrap a new, non-application Pivotal GemFire Server to add to a cluster. In other words, 'auto-reconnect'
|
||||
should not be enabled when _Spring Data for Pivotal GemFire_ is used to develop and build an Pivotal GemFire application that also happens
|
||||
should not be enabled when Spring Data for Pivotal GemFire is used to develop and build a Pivotal GemFire application that also happens
|
||||
to be a peer cache member of the Pivotal GemFire cluster.
|
||||
|
||||
The main reason for this is that most Pivotal GemFire applications use references to the Pivotal GemFire cache or Regions in order to
|
||||
perform data access operations. These references are "injected" by the Spring container into application components
|
||||
(e.g. DAOs or Repositories) for use by the application. When a peer member is forcefully disconnected from the rest
|
||||
The main reason for this restriction is that most Pivotal GemFire applications use references to the Pivotal GemFire cache or Regions in order to
|
||||
perform data access operations. These references are "`injected`" by the Spring container into application components
|
||||
(such as DAOs or Repositories) for use by the application. When a peer member is forcefully disconnected from the rest
|
||||
of the cluster, presumably because the peer member has become unresponsive or a network partition separates one or more
|
||||
peer members into a group too small to function as an independent distributed system, the peer member will shutdown
|
||||
and all Pivotal GemFire component references (e.g. Cache, Regions, etc) become invalid.
|
||||
peer members into a group too small to function as an independent distributed system, the peer member shuts down
|
||||
and all Pivotal GemFire component references (caches, regions, and others) become invalid.
|
||||
|
||||
Essentially, the current forced-disconnect processing logic in each peer member dismantles the system from the ground up.
|
||||
The JGroups stack shuts down, the Distributed System is put in a shutdown state and finally, the Cache is closed.
|
||||
The JGroups stack shuts down, the distributed system is put in a shutdown state and, finally, the cache is closed.
|
||||
Effectively, all memory references become stale and are lost.
|
||||
|
||||
After being disconnected from the Distributed System a peer member enters a "reconnecting" state and periodically
|
||||
attempts to rejoin the Distributed System. If the peer member succeeds in reconnecting, the member rebuilds
|
||||
its "view" of the Distributed System from existing members and receives a new Distributed System ID. Additionally, all
|
||||
Cache, Regions and other Pivotal GemFire components are reconstructed. Therefore, all old references, which may have been
|
||||
injected into application by the Spring container are now stale and no longer valid.
|
||||
After being disconnected from the distributed system, a peer member enters a "`reconnecting`" state and periodically
|
||||
attempts to rejoin the distributed system. If the peer member succeeds in reconnecting, the member rebuilds
|
||||
its "`view`" of the distributed system from existing members and receives a new distributed system ID. Additionally, all
|
||||
caches, regions, and other Pivotal GemFire components are reconstructed. Therefore, all old references, which may have been
|
||||
injected into application by the Spring container, are now stale and no longer valid.
|
||||
|
||||
Pivotal GemFire makes no guarantee, even when using the Pivotal GemFire public Java API, that application Cache, Region or other
|
||||
component references will be automatically refreshed by the reconnect operation. As such, Pivotal GemFire applications
|
||||
Pivotal GemFire makes no guarantee (even when using the Pivotal GemFire public Java API) that application cache, region, or other
|
||||
component references are automatically refreshed by the reconnect operation. As such, Pivotal GemFire applications
|
||||
must take care to refresh their own references.
|
||||
|
||||
Unfortunately, there is no way to be notified of a disconnect event, and subsequently, a reconnect event.
|
||||
If that were the case, the application developer would have a clean way to know when to call
|
||||
`ConfigurableApplicationContext.refresh()`, if even applicable for an application to do so, which is why
|
||||
this "feature" of Pivotal GemFire is not recommended for peer cache Pivotal GemFire applications.
|
||||
Unfortunately, there is no way to be notified of a disconnect event and, subsequently, a reconnect event.
|
||||
If that were the case, you would have a clean way to know when to call
|
||||
`ConfigurableApplicationContext.refresh()`, if it were even applicable for an application to do so, which is why
|
||||
this "`feature`" of Pivotal GemFire is not recommended for peer cache Pivotal GemFire applications.
|
||||
|
||||
For more information about 'auto-reconnect', see Pivotal GemFire's
|
||||
http://geode.apache.org/docs/guide/11/managing/autoreconnect/member-reconnect.html[product documentation].
|
||||
@@ -214,28 +214,28 @@ http://geode.apache.org/docs/guide/11/managing/autoreconnect/member-reconnect.ht
|
||||
=== Using Cluster-based Configuration
|
||||
|
||||
Pivotal GemFire's Cluster Configuration Service is a convenient way for any peer member joining the cluster to get
|
||||
a "consistent view" of the cluster by using the shared, persistent configuration maintained by a Locator.
|
||||
Using the Cluster-based Configuration ensures the peer member's configuration will be compatible with
|
||||
a "`consistent view`" of the cluster by using the shared, persistent configuration maintained by a locator.
|
||||
Using the cluster-based Configuration ensures the peer member's configuration is compatible with
|
||||
the Pivotal GemFire Distributed System when the member joins.
|
||||
|
||||
This feature of _Spring Data for Pivotal GemFire_ (setting the `use-cluster-configuration` attribute to `true`) works in the same way
|
||||
This feature of Spring Data for Pivotal GemFire (setting the `use-cluster-configuration` attribute to `true`) works in the same way
|
||||
as the `cache-xml-location` attribute, except the source of the Pivotal GemFire configuration meta-data comes from the network
|
||||
via a Locator as opposed to a native `cache.xml` file residing in the local file system.
|
||||
through a locator, as opposed to a native `cache.xml` file residing in the local file system.
|
||||
|
||||
All Pivotal GemFire native configuration meta-data, whether from `cache.xml` or from the Cluster Configuration Service,
|
||||
gets applied before any _Spring_ (XML) configuration meta-data. As such, _Spring's_ config serves to "augment" the
|
||||
native Pivotal GemFire configuration meta-data and would most likely be specific to the application.
|
||||
All Pivotal GemFire native configuration metadata, whether from `cache.xml` or from the Cluster Configuration Service,
|
||||
gets applied before any Spring (XML) configuration metadata. As a result, Spring's config serves to "`augment`" the
|
||||
native Pivotal GemFire configuration metadata and would most likely be specific to the application.
|
||||
|
||||
Again, to enable this feature, just specify the following in the _Spring_ XML config:
|
||||
Again, to enable this feature, specify the following in the Spring XML config:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:cache use-cluster-configuration="true"/>
|
||||
----
|
||||
|
||||
NOTE: While certain Pivotal GemFire tools, like _Gfsh_, have their actions "recorded" when schema-like changes are made
|
||||
(e.g. `gfsh>create region --name=Example --type=PARTITION`), _Spring Data for Pivotal GemFire's_ configuration meta-data
|
||||
is not recorded. The same is true when using Pivotal GemFire's public Java API directly; it too is not recorded.
|
||||
NOTE: While certain Pivotal GemFire tools, such as `Gfsh`, have their actions "`recorded`" when schema-like changes are made
|
||||
(for example, `gfsh>create region --name=Example --type=PARTITION`), Spring Data for Pivotal GemFire's configuration metadata
|
||||
is not recorded. The same is true when using Pivotal GemFire's public Java API directly. It, too, is not recorded.
|
||||
|
||||
For more information on Pivotal GemFire's Cluster Configuration Service, see the
|
||||
http://geode.apache.org/docs/guide/11/configuring/cluster_config/gfsh_persist.html[product documentation].
|
||||
@@ -243,9 +243,9 @@ http://geode.apache.org/docs/guide/11/configuring/cluster_config/gfsh_persist.ht
|
||||
[[bootstrap:cache:server]]
|
||||
== Configuring a Pivotal GemFire CacheServer
|
||||
|
||||
_Spring Data for Pivotal GemFire_ includes dedicated support for configuring a
|
||||
Spring Data for Pivotal GemFire includes dedicated support for configuring a
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/server/CacheServer.html[CacheServer],
|
||||
allowing complete configuration through the Spring container:
|
||||
allowing complete configuration through the Spring container, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -277,35 +277,34 @@ allowing complete configuration through the Spring container:
|
||||
</beans>
|
||||
----
|
||||
|
||||
The configuration above illustrates the `cache-server` element and the many options available.
|
||||
The preceding configuration shows the `cache-server` element and the many available options.
|
||||
|
||||
NOTE: Rather than hard-coding the port, this configuration uses _Spring's_
|
||||
NOTE: Rather than hard-coding the port, this configuration uses Spring's
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config-body-schemas-context[context]
|
||||
namespace to declare a `property-placeholder`.
|
||||
namespace to declare a `property-placeholder`. A
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-placeholderconfigurer[property placeholder]
|
||||
reads one or more properties files and then replaces property placeholders with values at runtime. This allows administrators
|
||||
to change values without having to touch the main application configuration. _Spring_ also provides the
|
||||
reads one or more properties files and then replaces property placeholders with values at runtime. Doing so lets administrators
|
||||
change values without having to touch the main application configuration. Spring also provides
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#expressions[SpEL]
|
||||
and the http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-environment[environment abstraction]
|
||||
and an http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-environment[environment abstraction]
|
||||
to support externalization of environment-specific properties from the main codebase, easing deployment
|
||||
across multiple machines.
|
||||
|
||||
NOTE: To avoid initialization problems, the `CacheServer` started by _Spring Data for Pivotal GemFire_ will start *after*
|
||||
the _Spring_ container has been fully initialized. This allows potential Regions, Listeners, Writers or Instantiators
|
||||
defined declaratively to be fully initialized and registered before the server starts accepting connections.
|
||||
Keep this in mind when programmatically configuring these elements as the server might start after your components
|
||||
NOTE: To avoid initialization problems, the `CacheServer` started by Spring Data for Pivotal GemFire starts *after*
|
||||
the Spring container has been fully initialized. Doing so lets potential regions, listeners, writers or instantiators that are
|
||||
defined declaratively be fully initialized and registered before the server starts accepting connections.
|
||||
Keep this in mind when programmatically configuring these elements, as the server might start after your components
|
||||
and thus not be seen by the clients connecting right away.
|
||||
|
||||
[[bootstrap:cache:client]]
|
||||
== Configuring a Pivotal GemFire ClientCache
|
||||
|
||||
In addition to defining a Pivotal GemFire peer http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/Cache.html[Cache],
|
||||
_Spring Data for Pivotal GemFire_ also supports the definition of a Pivotal GemFire http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientCache.html[ClientCache]
|
||||
in a _Spring_ context. A `ClientCache` definition is very similar in configuration and use to
|
||||
the Pivotal GemFire peer <<bootstrap:cache,Cache>> and is supported by the `org.springframework.data.gemfire.client.ClientCacheFactoryBean`.
|
||||
In addition to defining a Pivotal GemFire peer http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/Cache.html[cache],
|
||||
Spring Data for Pivotal GemFire also supports the definition of a Pivotal GemFire http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientCache.html[`ClientCache`]
|
||||
in a Spring context. A `ClientCache` definition is similar in configuration and use to
|
||||
the Pivotal GemFire peer <<bootstrap:cache,cache>> and is supported by the `org.springframework.data.gemfire.client.ClientCacheFactoryBean`.
|
||||
|
||||
The simplest definition of a Pivotal GemFire cache client using default configuration can be accomplished with the following
|
||||
declaration:
|
||||
The simplest definition of a Pivotal GemFire cache client using default configuration follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -314,16 +313,16 @@ declaration:
|
||||
</beans>
|
||||
----
|
||||
|
||||
`client-cache` supports many of the same options as the <<bootstrap:cache:advanced,cache>> element. However, as opposed
|
||||
to a *full-fledged* peer cache member, a cache client connects to a remote cache server through a Pool. By default,
|
||||
a Pool is created to connect to a server running on `localhost`, listening to port `40404`. The default Pool is used
|
||||
by all client Regions unless the Region is configured to use a specific Pool.
|
||||
`client-cache` supports many of the same options as the <<bootstrap:cache:advanced,cache>> element. However, as opposed
|
||||
to a full-fledged peer cache member, a cache client connects to a remote cache server through a pool. By default,
|
||||
a pool is created to connect to a server running on `localhost` and listening to port `40404`. The default pool is used
|
||||
by all client regions unless the region is configured to use a specific pool.
|
||||
|
||||
Pools can be defined with the `pool` element. This client-side Pool can be used to configure connectivity directly to
|
||||
a server for individual entities or the entire cache through one or more Locators.
|
||||
Pools can be defined with the `pool` element. This client-side pool can be used to configure connectivity directly to
|
||||
a server for individual entities or for the entire cache through one or more locators.
|
||||
|
||||
For example, to customize the default Pool used by the `client-cache`, the developer needs to define a Pool and wire it
|
||||
to the cache definition:
|
||||
For example, to customize the default pool used by the `client-cache`, the developer needs to define a Pool and wire it
|
||||
to the cache definition, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -336,15 +335,15 @@ to the cache definition:
|
||||
</beans>
|
||||
----
|
||||
|
||||
The `<client-cache>` element also has a `ready-for-events` attribute. If set to `true`, the client cache
|
||||
initialization will include a call to http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientCache.html#readyForEvents--[ClientCache.readyForEvents()].
|
||||
The `<client-cache>` element also has a `ready-for-events` attribute. If the attribute is set to `true`, the client cache
|
||||
initialization includes a call to http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientCache.html#readyForEvents[`ClientCache.readyForEvents()`].
|
||||
|
||||
Client-side configuration is covered in more detail in <<bootstrap:region:client>>.
|
||||
<<bootstrap:region:client>> covers client-side configuration in more detail.
|
||||
|
||||
[[bootstrap:cache:client:pool]]
|
||||
=== Pivotal GemFire's DEFAULT Pool and Spring Data for Pivotal GemFire Pool Definitions
|
||||
|
||||
If a Pivotal GemFire `ClientCache` is local-only, then no Pool definition is required. For instance, a developer may define:
|
||||
If a Pivotal GemFire `ClientCache` is local-only, then no Pool definition is required. For instance, you can define the following:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -353,18 +352,16 @@ If a Pivotal GemFire `ClientCache` is local-only, then no Pool definition is req
|
||||
<gfe:client-region id="Example" shortcut="LOCAL"/>
|
||||
----
|
||||
|
||||
In this case, the "Example" Region is `LOCAL` and no data is distributed between the client and a server, therefore,
|
||||
no Pool is necessary. This is true for any client-side, local-only Region, as defined by the Pivotal GemFire's
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
|
||||
In this case, the `Example` Region is `LOCAL` and no data is distributed between the client and a server. Therefore,
|
||||
no pool is necessary. This is true for any client-side, local-only region, as defined by the Pivotal GemFire's
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/client/ClientRegionShortcut.html[`ClientRegionShortcut`]
|
||||
(all `LOCAL_*` shortcuts).
|
||||
|
||||
However, if a client Region is a (caching) proxy to a server-side Region, then a Pool is required. There are several
|
||||
ways to define and use a Pool in this case.
|
||||
However, if a client Region is a (caching) proxy to a server-side Region, a pool is required. In that case, there are several
|
||||
ways to define and use a Pool.
|
||||
|
||||
When a client cache, Pool and proxy-based Region are all defined, but not explicitly identified, _Spring Data for Pivotal GemFire_
|
||||
will resolve the references automatically for you.
|
||||
|
||||
For example:
|
||||
When a client cache, a pool, and a proxy-based region are all defined but not explicitly identified, Spring Data for Pivotal GemFire
|
||||
resolves the references automatically, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -377,11 +374,11 @@ For example:
|
||||
<gfe:client-region id="Example" shortcut="PROXY"/>
|
||||
----
|
||||
|
||||
In the example above, the client cache is identified as `gemfireCache`, the Pool as `gemfirePool` and the client Region
|
||||
as "Example". However, the client cache will initialize Pivotal GemFire's DEFAULT Pool from `gemfirePool` and the client Region
|
||||
will use the `gemfirePool` when distributing data between the client and the server.
|
||||
In the preceding example, the client cache is identified as `gemfireCache`, the Pool as `gemfirePool`, and the client region
|
||||
as `Example`. However, the client cache initializes Pivotal GemFire's `DEFAULT` pool from `gemfirePool`, and the client Region
|
||||
uses the `gemfirePool` when distributing data between the client and the server.
|
||||
|
||||
Basically, _Spring Data for Pivotal GemFire_ resolves the above configuration to the following:
|
||||
Basically, Spring Data for Pivotal GemFire resolves the preceding configuration to the following:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -394,8 +391,8 @@ Basically, _Spring Data for Pivotal GemFire_ resolves the above configuration to
|
||||
<gfe:client-region id="Example" cache-ref="gemfireCache" pool-name="gemfirePool" shortcut="PROXY"/>
|
||||
----
|
||||
|
||||
Pivotal GemFire still creates a Pool called "DEFAULT". _Spring Data for Pivotal GemFire_ will just cause the "DEFAULT" Pool to be
|
||||
initialized from the `gemfirePool`. This is useful in situations where multiple Pools are defined and client Regions
|
||||
Pivotal GemFire still creates a pool called `DEFAULT`. Spring Data for Pivotal GemFire causes the `DEFAULT` pool to be
|
||||
initialized from the `gemfirePool`. Doing so is useful in situations where multiple pools are defined and client regions
|
||||
are using separate Pools.
|
||||
|
||||
Consider the following:
|
||||
@@ -419,19 +416,18 @@ Consider the following:
|
||||
<gfe:client-region id="YetAnotherExample" shortcut="LOCAL"/>
|
||||
----
|
||||
|
||||
In this setup, the Pivotal GemFire client cache's "DEFAULT" Pool is initialized from "locatorPool" as specified with the
|
||||
`pool-name` attribute. There is no _Spring Data for Pivotal GemFire_-defined `gemfirePool` since both Pools were explicitly
|
||||
identified (named) "locatorPool" and "serverPool", respectively.
|
||||
In this setup, the Pivotal GemFire client cache's `DEFAULT` pool is initialized from `locatorPool`, as specified by the
|
||||
`pool-name` attribute. There is no Spring Data for Pivotal GemFire-defined `gemfirePool`, since both pools were explicitly
|
||||
identified (named) -- `locatorPool` and `serverPool`, respectively.
|
||||
|
||||
The "Example" Region explicitly refers to and uses the "serverPool" exclusively. The "AnotherExample" Region uses
|
||||
Pivotal GemFire's "DEFAULT" Pool, which was configured from the "locatorPool" based on the client cache bean definition's
|
||||
The `Example` region explicitly refers to and exclusively uses the `serverPool`. The `AnotherExample` region uses
|
||||
Pivotal GemFire's `DEFAULT` pool, which was configured from the `locatorPool` based on the client cache bean definition's
|
||||
`pool-name` attribute.
|
||||
|
||||
Finally, the "YetAnotherExample" Region will not use a Pool since it is `LOCAL`.
|
||||
Finally, the `YetAnotherExample` egion does not use a Pool, because it is `LOCAL`.
|
||||
|
||||
NOTE: The "AnotherExample" Region would first look for a Pool bean named `gemfirePool`, but that would require
|
||||
the definition of an anonymous Pool bean (i.e. `<gfe:pool/>`) or a Pool bean explicitly named `gemfirePool`
|
||||
(e.g. `<gfe:pool id="gemfirePool"/>`).
|
||||
NOTE: The `AnotherExample` region would first look for a pool bean named `gemfirePool`, but that would require
|
||||
the definition of an anonymous Pool bean (that is, `<gfe:pool/>`) or a pool bean explicitly named `gemfirePool`
|
||||
(for example, `<gfe:pool id="gemfirePool"/>`).
|
||||
|
||||
NOTE: We could have either named "locatorPool", "gemfirePool", or made the Pool bean definition anonymous
|
||||
and it would have the same effect as the above configuration.
|
||||
NOTE: If we either changed the name of `locatorPool` to `gemfirePool` or made the pool bean definition be anonymous, it would have the same effect as the preceding configuration.
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
[[data-access]]
|
||||
= Using the Data Access Namespace
|
||||
|
||||
In addition to the core XML namespace (`gfe`), _Spring Data for Pivotal GemFire_ provides a data access XML namespace (`gfe-data`),
|
||||
In addition to the core XML namespace (`gfe`), Spring Data for Pivotal GemFire provides a data access XML namespace (`gfe-data`),
|
||||
which is primarily intended to simplify the development of Pivotal GemFire client applications. This namespace currently contains
|
||||
support for Pivotal GemFire <<gemfire-repositories, Repositories>> and function <<function-execution, execution>>
|
||||
as well as includes a `<datasource>` tag offering a convenient way to connect to a Pivotal GemFire cluster.
|
||||
support for Pivotal GemFire <<gemfire-repositories, Repositories>> and function <<function-execution, execution>>,
|
||||
as well as a `<datasource>` tag that offers a convenient way to connect to a Pivotal GemFire cluster.
|
||||
|
||||
[[data-access:datasource]]
|
||||
== An Easy Way to Connect to Pivotal GemFire
|
||||
|
||||
For many applications, a basic connection to a Pivotal GemFire data grid using default values is sufficient.
|
||||
_Spring Data for Pivotal GemFire's_ `<datasource>` tag provides a simple way to access data. The data source creates
|
||||
a `ClientCache` and connection `Pool`. In addition, it will query the cluster servers for all existing root Regions
|
||||
and create an (empty) client Region proxy for each one.
|
||||
Spring Data for Pivotal GemFire's `<datasource>` tag provides a simple way to access data. The data source creates
|
||||
a `ClientCache` and connection `Pool`. In addition, it queries the cluster servers for all existing root Regions
|
||||
and creates an (empty) client Region proxy for each one.
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -22,12 +22,12 @@ and create an (empty) client Region proxy for each one.
|
||||
----
|
||||
|
||||
The `<datasource>` tag is syntactically similar to `<gfe:pool>`. It may be configured with one or more nested `locator`
|
||||
or `server` tags to connect to an existing data grid. Additionally, all attributes available to configure a Pool
|
||||
are supported. This configuration will automatically create client Region beans for each Region defined on
|
||||
cluster members connected to the Locator, so they may be seamlessly referenced by _Spring Data_ mapping annotations,
|
||||
`GemfireTemplate`, and wired into application classes.
|
||||
or `server` tags to connect to an existing data grid. Additionally, all attributes available to configure a pool
|
||||
are supported. This configuration automatically creates client region beans for each region defined on
|
||||
cluster members connected to the locator, so they can be seamlessly referenced by Spring Data mapping annotations
|
||||
(`GemfireTemplate`) and wired into application classes.
|
||||
|
||||
Of course, you can explicitly configure client Regions. For example, if you want to cache data in local memory:
|
||||
Of course, you can explicitly configure client regions. For example, if you want to cache data in local memory, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
[[bootstrap:diskstore]]
|
||||
= Configuring a DiskStore
|
||||
|
||||
_Spring Data for Pivotal GemFire_ supports `DiskStore` configuration and creation via the `disk-store` element.
|
||||
|
||||
For example:
|
||||
Spring Data for Pivotal GemFire supports `DiskStore` configuration and creation through the `disk-store` element, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -14,10 +12,10 @@ For example:
|
||||
</gfe:disk-store>
|
||||
----
|
||||
|
||||
`DiskStores` are used by Regions for file system persistent backup and overflow of evicted entries
|
||||
as well as persistent backup for WAN Gateways. Multiple Pivotal GemFire components may share the same `DiskStore`.
|
||||
Additionally, multiple file system directories may be defined for a single `DiskStore` as shown in the example above.
|
||||
`DiskStore` instances are used by regions for file system persistent backup and overflow of evicted entries
|
||||
as well as persistent backup for WAN Gateways. Multiple Pivotal GemFire components may share the same `DiskStore`.
|
||||
Additionally, multiple file system directories may be defined for a single `DiskStore`, as shown in the preceding example.
|
||||
|
||||
Please refer to Pivotal GemFire's documentation for a complete explanation of
|
||||
See Pivotal GemFire's documentation for a complete explanation of
|
||||
http://gemfire.docs.pivotal.io/95/geode/developing/storing_data_on_disk/chapter_overview.html[Persistence and Overflow]
|
||||
along with configuration options on `DiskStores`.
|
||||
and configuration options on `DiskStore` instances.
|
||||
|
||||
@@ -1,83 +1,80 @@
|
||||
[[function-annotations]]
|
||||
= Annotation Support for Function Execution
|
||||
|
||||
== Introduction
|
||||
|
||||
_Spring Data for Pivotal GemFire_ includes annotation support to simplify working with Pivotal GemFire
|
||||
http://geode.apache.org/docs/guide/11/developing/function_exec/chapter_overview.html[Function Execution].
|
||||
Under-the-hood, the Pivotal GemFire API provides classes to implement and register Pivotal GemFire
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/Function.html[Functions]
|
||||
Spring Data for Pivotal GemFire includes annotation support to simplify working with Pivotal GemFire
|
||||
http://geode.apache.org/docs/guide/11/developing/function_exec/chapter_overview.html[function execution].
|
||||
Under the hood, the Pivotal GemFire API provides classes to implement and register Pivotal GemFire
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/Function.html[functions]
|
||||
that are deployed on Pivotal GemFire servers, which may then be invoked by other peer member applications
|
||||
or remotely from cache clients.
|
||||
|
||||
Functions can execute in parallel, distributed among multiple Pivotal GemFire servers in the cluster, aggregating results
|
||||
with the map-reduce pattern that are sent back to the caller. Functions can also be targeted to run on a single server
|
||||
or Region. The Pivotal GemFire API supports remote execution of Functions targeted using various predefined scopes:
|
||||
on Region, on members [in groups], on servers, etc. The implementation and execution of remote Functions,
|
||||
with the map-reduce pattern that are sent back to the caller. Functions can also be targeted to run on a single server
|
||||
or region. The Pivotal GemFire API supports remote execution of functions targeted by using various predefined scopes:
|
||||
on region, on members (in groups), on servers, and others. The implementation and execution of remote functions,
|
||||
as with any RPC protocol, requires some boilerplate code.
|
||||
|
||||
_Spring Data for Pivotal GemFire_, true to _Spring's_ core value proposition, aims to hide the mechanics of remote Function execution
|
||||
and allow developers to focus on core POJO programming and business logic. To this end, _Spring Data for Pivotal GemFire_ introduces
|
||||
annotations to declaratively register public methods of a POJO class as Pivotal GemFire Functions along with the ability to
|
||||
invoke registered Functions [remotely] via annotated interfaces.
|
||||
Spring Data for Pivotal GemFire, true to Spring's core value proposition, aims to hide the mechanics of remote function execution
|
||||
and let you focus on core POJO programming and business logic. To this end, Spring Data for Pivotal GemFire introduces
|
||||
annotations to declaratively register the public methods of a POJO class as Pivotal GemFire functions along with the ability to
|
||||
invoke registered functions (including remotely) by using annotated interfaces.
|
||||
|
||||
== Implementation vs Execution
|
||||
== Implementation Versus Execution
|
||||
|
||||
There are two separate concerns to address implementation and execution.
|
||||
|
||||
First is Function implementation (server-side), which must interact with the
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/FunctionContext.html[FunctionContext]
|
||||
The first is function implementation (server-side), which must interact with the
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/FunctionContext.html[`FunctionContext`]
|
||||
to access the invocation arguments,
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/ResultSender.html[ResultsSender]
|
||||
as well as other execution context information. The Function implementation typically accesses the Cache and/or Regions
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/ResultSender.html[`ResultsSender`],
|
||||
and other execution context information. The function implementation typically accesses the cache and regions
|
||||
and is registered with the
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/FunctionService.html[FunctionService]
|
||||
under a unique Id.
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/FunctionService.html[`FunctionService`]
|
||||
under a unique ID.
|
||||
|
||||
A cache client application invoking a Function does not depend on the implementation. To invoke a Function,
|
||||
A cache client application invoking a function does not depend on the implementation. To invoke a function,
|
||||
the application instantiates an
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/Execution.html[Execution]
|
||||
providing the Function ID, invocation arguments and the Function target, which defines its scope:
|
||||
Region, server, servers, member or members. If the Function produces a result, the invoker uses a
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/ResultCollector.html[ResultCollector]
|
||||
to aggregate and acquire the execution results. In certain cases, a custom `ResultCollector` implementation
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/Execution.html[`Execution`]
|
||||
providing the function ID, invocation arguments, and the function target, which defines its scope:
|
||||
region, server, servers, member, or members. If the function produces a result, the invoker uses a
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/ResultCollector.html[`ResultCollector`]
|
||||
to aggregate and acquire the execution results. In certain cases, a custom `ResultCollector` implementation
|
||||
is required and may be registered with the `Execution`.
|
||||
|
||||
NOTE: 'Client' and 'Server' are used here in the context of Function execution, which may have a different meaning
|
||||
than client and server in Pivotal GemFire's client-server topology. While it is common for an application using a `ClientCache`
|
||||
to invoke a Function on one or more Pivotal GemFire servers in a cluster, it is also possible to execute Functions
|
||||
NOTE: 'Client' and 'Server' are used here in the context of function execution, which may have a different meaning
|
||||
than client and server in Pivotal GemFire's client-server topology. While it is common for an application using a `ClientCache`
|
||||
to invoke a function on one or more Pivotal GemFire servers in a cluster, it is also possible to execute functions
|
||||
in a peer-to-peer (P2P) configuration, where the application is a member of the cluster hosting a peer `Cache`.
|
||||
Keep in mind that a peer member cache application is subject to all the same constraints of being a peer member
|
||||
Keep in mind that a peer member cache application is subject to all the constraints of being a peer member
|
||||
of the cluster.
|
||||
|
||||
[[function-implementation]]
|
||||
== Implementing a Function
|
||||
|
||||
Using Pivotal GemFire APIs, the `FunctionContext` provides a runtime invocation context that includes the client's
|
||||
calling arguments and a `ResultSender` implementation to send results back to the client. Additionally,
|
||||
if the Function is executed on a Region, the `FunctionContext` is actually an instance of `RegionFunctionContext`,
|
||||
which provides additional information such as the target Region on which the Function was invoked
|
||||
and any Filter (set of specific keys) associated with the `Execution`, etc. If the Region is a PARTITION Region,
|
||||
the Function should use the `PartitionRegionHelper` to extract only the local data.
|
||||
calling arguments and a `ResultSender` implementation to send results back to the client. Additionally,
|
||||
if the function is executed on a region, the `FunctionContext` is actually an instance of `RegionFunctionContext`,
|
||||
which provides additional information, such as the target region on which the function was invoked,
|
||||
any filter (a set of specific keys) associated with the `Execution`, and so on. If the region is a `PARTITION` region,
|
||||
the function should use the `PartitionRegionHelper` to extract only the local data.
|
||||
|
||||
Using _Spring_, a developer can write a simple POJO and use the _Spring_ container to bind one or more of it's
|
||||
public methods to a Function. The signature for a POJO method intended to be used as a Function must generally
|
||||
conform to the client's execution arguments. However, in the case of a Region execution, the Region data
|
||||
may also be provided (presumably the data held in the local partition if the Region is a PARTITION Region).
|
||||
Additionally, the Function may require the Filter that was applied, if any. This suggests that the client and server
|
||||
By using Spring, you can write a simple POJO and use the Spring container to bind one or more of your POJO's
|
||||
public methods to a function. The signature for a POJO method intended to be used as a function must generally
|
||||
conform to the client's execution arguments. However, in the case of a region execution, the region data
|
||||
may also be provided (presumably the data is held in the local partition if the region is a `PARTITION` region).
|
||||
Additionally, the function may require the filter that was applied, if any. This suggests that the client and server
|
||||
share a contract for the calling arguments but that the method signature may include additional parameters
|
||||
to pass values provided by the `FunctionContext`. One possibility is for the client and server to share
|
||||
a common interface, but this is not strictly required. The only constraint is that the method signature includes
|
||||
the same sequence of calling arguments with which the Function was invoked after the additional parameters
|
||||
to pass values provided by the `FunctionContext`. One possibility is for the client and server to share
|
||||
a common interface, but this is not strictly required. The only constraint is that the method signature includes
|
||||
the same sequence of calling arguments with which the function was invoked after the additional parameters
|
||||
are resolved.
|
||||
|
||||
For example, suppose the client provides a String and int as the calling arguments. These are provided
|
||||
in the `FunctionContext` as an array:
|
||||
For example, suppose the client provides a `String` and an `int` as the calling arguments. These are provided
|
||||
in the `FunctionContext` as an array, as the following example shows:
|
||||
|
||||
`Object[] args = new Object[] { "test", 123 };`
|
||||
|
||||
Then, the _Spring_ container should be able to bind to any method signature similar to the following.
|
||||
Let's ignore the return type for the moment:
|
||||
The Spring container should be able to bind to any method signature similar to the following (ignoring the return type for the moment):
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -90,18 +87,18 @@ public void method5(String s1, ResultSender rs, int i2);
|
||||
public void method6(FunctionContest context);
|
||||
----
|
||||
|
||||
The general rule is that once any additional arguments, i.e. Region data and Filter, are resolved,
|
||||
the remaining arguments must correspond exactly, in order and type, to the expected Function method parameters.
|
||||
The method's return type must be void or a type that may be serialized (either as a `java.io.Serializable`,
|
||||
`DataSerializable` or `PdxSerializable`). The latter is also a requirement for the calling arguments.
|
||||
The Region data should normally be defined as a Map, to facilitate unit testing, but may also be of type Region
|
||||
if necessary. As shown in the example above, it is also valid to pass the `FunctionContext` itself,
|
||||
or the `ResultSender`, if you need to control how the results are returned to the client.
|
||||
The general rule is that once any additional arguments (that is, region data and filter) are resolved,
|
||||
the remaining arguments must correspond exactly, in order and type, to the expected function method parameters.
|
||||
The method's return type must be void or a type that may be serialized (as a `java.io.Serializable`,
|
||||
`DataSerializable`, or `PdxSerializable`). The latter is also a requirement for the calling arguments.
|
||||
The region data should normally be defined as a `Map`, to facilitate unit testing, but may also be of type region,
|
||||
if necessary. As shown in the preceding example, it is also valid to pass the `FunctionContext` itself
|
||||
or the `ResultSender` if you need to control how the results are returned to the client.
|
||||
|
||||
=== Annotations for Function Implementation
|
||||
|
||||
The following example illustrates how SDG's Function annotations are used to expose POJO methods
|
||||
as Pivotal GemFire Functions:
|
||||
The following example shows how SDG's function annotations are used to expose POJO methods
|
||||
as Pivotal GemFire functions:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -120,58 +117,56 @@ public class ApplicationFunctions {
|
||||
}
|
||||
----
|
||||
|
||||
Note, the class itself must be registered as a _Spring_ bean and each Pivotal GemFire Function is annotated
|
||||
with `@GemfireFunction`. In this example, _Spring's_ `@Component` annotation was used, but you may register the bean
|
||||
by any method supported by _Spring_ (e.g. XML configuration or with a Java configuration class using _Spring Boot_).
|
||||
This allows the _Spring_ container to create an instance of this class and wrap it in a
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/function/PojoFunctionWrapper.html[PojoFunctionWrapper].
|
||||
_Spring_ creates a wrapper instance for each method annotated with `@GemfireFunction`. Each wrapper instance shares
|
||||
Note that the class itself must be registered as a Spring bean and each Pivotal GemFire Function is annotated
|
||||
with `@GemfireFunction`. In the preceding example, Spring's `@Component` annotation was used, but you can register the bean
|
||||
by using any method supported by Spring (such as XML configuration or with a Java configuration class when using Spring Boot).
|
||||
This lets the Spring container create an instance of this class and wrap it in a
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/function/PojoFunctionWrapper.html[`PojoFunctionWrapper`].
|
||||
Spring creates a wrapper instance for each method annotated with `@GemfireFunction`. Each wrapper instance shares
|
||||
the same target object instance to invoke the corresponding method.
|
||||
|
||||
TIP: The fact that the POJO Function class is a _Spring_ bean may offer other benefits since it shares
|
||||
the `ApplicationContext` with Pivotal GemFire components such as the Cache and Regions. These may be injected into the class
|
||||
TIP: The fact that the POJO Function class is a Spring bean may offer other benefits, since it shares
|
||||
the `ApplicationContext` with Pivotal GemFire components, such as the cache and regions. These may be injected into the class
|
||||
if necessary.
|
||||
|
||||
_Spring_ creates the wrapper class and registers the Function(s) with Pivotal GemFire's Function Service. The Function id used
|
||||
to register the Functions must be unique. Using convention it defaults to the simple (unqualified) method name.
|
||||
The name can be explicitly defined using the `id` attribute of the `@GemfireFunction` annotation.
|
||||
Spring creates the wrapper class and registers the functions with Pivotal GemFire's function service. The function ID used
|
||||
to register each function must be unique. By using convention, it defaults to the simple (unqualified) method name.
|
||||
The name can be explicitly defined by using the `id` attribute of the `@GemfireFunction` annotation.
|
||||
The `@GemfireFunction` annotation also provides other configuration attributes, `HA` and `optimizedForWrite`,
|
||||
which correspond to properties defined by Pivotal GemFire's
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/Function.html[Function] interface.
|
||||
If the method's return type is void, then the `hasResult` property is automatically set to `false`;
|
||||
otherwise, if the method returns a value the `hasResult` attributes is set to `true`.
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/Function.html[`Function`] interface.
|
||||
If the method's return type is `void`, then the `hasResult` property is automatically set to `false`.
|
||||
Otherwise, if the method returns a value, the `hasResult` attributes is set to `true`.
|
||||
|
||||
Even for `void` return types, the annotation's `hasResult` attribute can be set to `true` to override this convention,
|
||||
as shown in the `functionWithContext` method above. Presumably, the intention is to use the `ResultSender` directly
|
||||
as shown in the `functionWithContext` method show previously. Presumably, the intention is to use the `ResultSender` directly
|
||||
to send results to the caller.
|
||||
|
||||
The `PojoFunctionWrapper` implements Pivotal GemFire's `Function` interface, binds method parameters and invokes the target method
|
||||
in its `execute()` method. It also sends the method's return value using the `ResultSender`.
|
||||
The `PojoFunctionWrapper` implements Pivotal GemFire's `Function` interface, binds method parameters, and invokes the target method
|
||||
in its `execute()` method. It also sends the method's return value by using the `ResultSender`.
|
||||
|
||||
=== Batching Results
|
||||
|
||||
If the return type is an array or Collection, then some consideration must be given to how the results are returned.
|
||||
By default, the `PojoFunctionWrapper` returns the entire array or Collection at once. If the number of elements
|
||||
in the array or Collection quite is large, it may incur a performance penalty. To divide the payload into smaller,
|
||||
more maneable chunks, you can set the `batchSize` attribute, as illustrated in `function2`, above.
|
||||
If the return type is an array or `Collection`, then some consideration must be given to how the results are returned.
|
||||
By default, the `PojoFunctionWrapper` returns the entire array or `Collection` at once. If the number of elements
|
||||
in the array or `Collection` is quite large, it may incur a performance penalty. To divide the payload into smaller,
|
||||
more manageable chunks, you can set the `batchSize` attribute, as illustrated in `function2`, shown earlier.
|
||||
|
||||
TIP: If you need more control of the `ResultSender`, especially if the method itself would use too much memory
|
||||
to create the Collection, you can pass the `ResultSender`, or access it via the `FunctionContext` and use it directly
|
||||
to create the `Collection`, you can pass the `ResultSender` or access it through the `FunctionContext` and use it directly
|
||||
within the method to sends results back to the caller.
|
||||
|
||||
=== Enabling Annotation Processing
|
||||
|
||||
In accordance with _Spring_ standards, you must explicitly activate annotation processing for `@GemfireFunction`
|
||||
annotations.
|
||||
|
||||
Using XML:
|
||||
In accordance with Spring standards, you must explicitly activate annotation processing for `@GemfireFunction`
|
||||
annotations. The following example activates annotation processing with XML:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:annotation-driven/>
|
||||
----
|
||||
|
||||
Or by annotating a Java configuration class:
|
||||
The following example activates annotations by annotating a Java configuration class:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -183,31 +178,31 @@ class ApplicationConfiguration { .. }
|
||||
[[function-execution]]
|
||||
== Executing a Function
|
||||
|
||||
A process invoking a remote Function needs to provide the Function's ID, calling arguments, the execution target
|
||||
(onRegion, onServers, onServer, onMember, onMembers) and optionally, a Filter set. Using _Spring Data for Pivotal GemFire_,
|
||||
all a developer need do is define an interface supported by annotations. _Spring_ will create a dynamic proxy
|
||||
for the interface, which will use the `FunctionService` to create an `Execution`, invoke the `Execution` and coerce
|
||||
the results to the defined return type, if necessary. This technique is very similar to the way
|
||||
_Spring Data for Pivotal GemFire's Repository extension_ works, thus some of the configuration and concepts should be familiar.
|
||||
Generally, a single interface definition maps to multiple Function executions, one corresponding to each method
|
||||
A process that invokes a remote function needs to provide the function's ID, calling arguments, the execution target
|
||||
(`onRegion`, `onServers`, `onServer`, `onMember`, or `onMembers`) and (optionally) a filter set. By using Spring Data for Pivotal GemFire,
|
||||
all you need do is define an interface supported by annotations. Spring creates a dynamic proxy
|
||||
for the interface, which uses the `FunctionService` to create an `Execution`, invoke the `Execution`, and (if necessary) coerce
|
||||
the results to the defined return type. This technique is similar to the way
|
||||
Spring Data for Pivotal GemFire's repository extension works. Thus, some of the configuration and concepts should be familiar.
|
||||
Generally, a single interface definition maps to multiple function executions, one corresponding to each method
|
||||
defined in the interface.
|
||||
|
||||
=== Annotations for Function Execution
|
||||
|
||||
To support client-side Function execution, the following SDG Function annotations are provided: `@OnRegion`,
|
||||
`@OnServer`, `@OnServers`, `@OnMember`, `@OnMembers`. These annotations correspond to the `Execution` implementations
|
||||
prodided by Pivotal GemFire's
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/FunctionService.html[FunctionService].
|
||||
`@OnServer`, `@OnServers`, `@OnMember`, and `@OnMembers`. These annotations correspond to the `Execution` implementations
|
||||
provided by Pivotal GemFire's
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/FunctionService.html[`FunctionService`].
|
||||
Each annotation exposes the appropriate attributes. These annotations also provide an optional
|
||||
`resultCollector` attribute whose value is the name of a _Spring_ bean implementing the
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/ResultCollector.html[ResultCollector]
|
||||
`resultCollector` attribute whose value is the name of a Spring bean implementing the
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/ResultCollector.html[`ResultCollector`]
|
||||
to use for the execution.
|
||||
|
||||
CAUTION: The proxy interface binds all declared methods to the same execution configuration. Although, it is expected
|
||||
that single method interfaces will be common, all methods in the interface are backed by the same proxy instance
|
||||
CAUTION: The proxy interface binds all declared methods to the same execution configuration. Although it is expected
|
||||
that single method interfaces are common, all methods in the interface are backed by the same proxy instance
|
||||
and therefore all share the same configuration.
|
||||
|
||||
Here are a few examples:
|
||||
The following listing shows a few examples:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -222,24 +217,24 @@ public interface FunctionExecution {
|
||||
}
|
||||
----
|
||||
|
||||
By default, the Function ID is the simple (unqualified) method name. The `@FunctionId` annotation can be used
|
||||
to bind this invocation to a different Function ID.
|
||||
By default, the function ID is the simple (unqualified) method name. The `@FunctionId` annotation can be used
|
||||
to bind this invocation to a different function ID.
|
||||
|
||||
=== Enabling Annotation Processing
|
||||
|
||||
The client-side uses _Spring's_ classpath component scanning capability to discover annotated interfaces. To enable
|
||||
Function execution annotation processing in XML:
|
||||
The client-side uses Spring's classpath component scanning capability to discover annotated interfaces. To enable
|
||||
function execution annotation processing in XML, insert the following element in your XML configuration:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe-data:function-executions base-package="org.example.myapp.gemfire.functions"/>
|
||||
----
|
||||
|
||||
The `function-executions` element is provided in the `gfe-data` namespace. The `base-package` attribute is required
|
||||
to avoid scanning the entire classpath. Additional filters are provided as described in the _Spring_
|
||||
The `function-executions` element is provided in the `gfe-data` namespace. The `base-package` attribute is required,
|
||||
to avoid scanning the entire classpath. Additional filters are provided as described in the Spring
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-scanning-filters[reference documentation].
|
||||
|
||||
Optionally, a developer can annotate her Java configuration class:
|
||||
Optionally, you can annotate your Java configuration class as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -266,8 +261,8 @@ public class MyApplication {
|
||||
}
|
||||
----
|
||||
|
||||
Alternately, you can use a Function execution template directly. For example, `GemfireOnRegionFunctionTemplate`
|
||||
creates an `onRegion` Function `Execution`.
|
||||
Alternately, you can use a function execution template directly. In the following example, the `GemfireOnRegionFunctionTemplate`
|
||||
creates an `onRegion` function `Execution`:
|
||||
|
||||
.Using the `GemfireOnRegionFunctionTemplate`
|
||||
====
|
||||
@@ -280,22 +275,22 @@ String result = template.executeAndExtract("someFunction", myFilter, "hello", "w
|
||||
----
|
||||
====
|
||||
|
||||
Internally, Function `Executions` always return a `List`. `executeAndExtract` assumes a singleton `List`
|
||||
containing the result and will attempt to coerce that value into the requested type. There is also
|
||||
an `execute` method that returns the `List` as is. The first parameter is the Function ID.
|
||||
The Filter argument is optional. The following arguments are a variable argument `List`.
|
||||
Internally, function `Executions` always return a `List`. `executeAndExtract` assumes a singleton `List`
|
||||
containing the result and attempts to coerce that value into the requested type. There is also
|
||||
an `execute` method that returns the `List` as is. The first parameter is the function ID.
|
||||
The filter argument is optional. The remaining arguments are a variable argument `List`.
|
||||
|
||||
[[function-execution-pdx]]
|
||||
== Function Execution with PDX
|
||||
|
||||
When using _Spring Data for Pivotal GemFire's_ Function annotation support combined with Pivotal GemFire's
|
||||
When using Spring Data for Pivotal GemFire's function annotation support combined with Pivotal GemFire's
|
||||
http://geode.apache.org/docs/guide/11/developing/data_serialization/gemfire_pdx_serialization.html[PDX Serialization],
|
||||
there are a few logistical things to keep in mind.
|
||||
|
||||
As explained above, and by way of example, typically developers will define Pivotal GemFire Functions using POJO classes
|
||||
As explained earlier in this section, and by way of example, you should typically define Pivotal GemFire functions by using POJO classes
|
||||
annotated with Spring Data for Pivotal GemFire
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/function/annotation/package-summary.html[Function annotations]
|
||||
like so...
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/function/annotation/package-summary.html[function annotations],
|
||||
as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -307,11 +302,11 @@ public class OrderFunctions {
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: The Integer type, count parameter is arbitrary as is the separation of the `Order` class and `OrderSource` Enum,
|
||||
NOTE: The `Integer` type `count` parameter is arbitrary, as is the separation of the `Order` class and `OrderSource` enum,
|
||||
which might be logical to combine. However, the arguments were setup this way to demonstrate the problem with
|
||||
Function executions in the context of PDX.
|
||||
function executions in the context of PDX.
|
||||
|
||||
Your `Order` and `OrderSource` enum might be as follows...
|
||||
Your `Order` and `OrderSource` enum might be as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -334,7 +329,7 @@ public enum OrderSource {
|
||||
}
|
||||
----
|
||||
|
||||
Of course, a developer may define a Function `Execution` interface to call the 'process' Pivotal GemFire Server Function...
|
||||
Of course, you can define a function `Execution` interface to call the 'process' Pivotal GemFire server function, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -344,78 +339,78 @@ public interface OrderProcessingFunctions {
|
||||
}
|
||||
----
|
||||
|
||||
Clearly, this `process(..)` `Order` Function is being called from a client-side with a `ClientCache`
|
||||
(i.e. `<gfe:client-cache/>`) based application. This implies that the Function arguments must also be serializable.
|
||||
The same is true when invoking peer-to-peer member Functions (e.g. `@OnMember(s)) between peers in the cluster.
|
||||
Any form of `distribution` requires the data transmitted between client and server, or peers, to be serialized.
|
||||
Clearly, this `process(..)` `Order` Function is being called from a client-side with an application based on `ClientCache`
|
||||
(that is `<gfe:client-cache/>`). This implies that the function arguments must also be serializable.
|
||||
The same is true when invoking peer-to-peer member functions (such as `@OnMember(s)) between peers in the cluster.
|
||||
Any form of `distribution` requires the data transmitted between client and server (or peers) to be serialized.
|
||||
|
||||
Now, if the developer has configured Pivotal GemFire to use PDX for serialization (instead of Java serialization, for instance)
|
||||
it is common for developers to also set the `pdx-read-serialized` attribute to *true* in their configuration
|
||||
of the Pivotal GemFire server(s)...
|
||||
Now, if you have configured Pivotal GemFire to use PDX for serialization (instead of Java serialization, for instance)
|
||||
you can also set the `pdx-read-serialized` attribute to `true` in your configuration
|
||||
of the Pivotal GemFire server(s), as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:cache ... pdx-read-serialized="true"/>
|
||||
----
|
||||
|
||||
Or from a Pivotal GemFire cache client application...
|
||||
Alternatively, you can set the `pdx-read-serialized` attribute to `true` for a Pivotal GemFire cache client application, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:client-cache ... pdx-read-serialized="true"/>
|
||||
----
|
||||
|
||||
This causes all values read from the cache (i.e. Regions) as well as information passed between client and servers,
|
||||
or peers, to remain in serialized form, including, but not limited to, Function arguments.
|
||||
Doing so causes all values read from the cache (that is, regions) as well as information passed between client and servers
|
||||
(or peers) to remain in serialized form, including, but not limited to, function arguments.
|
||||
|
||||
Pivotal GemFire will only serialize application domain object types that you have specifically configured (registered),
|
||||
with either Pivotal GemFire's
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[ReflectionBasedAutoSerializer],
|
||||
or specifically (and recommended) using a "custom" Pivotal GemFire
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxSerializer.html[PdxSerializer]. If you are using
|
||||
_Spring Data for Pivotal GemFire's_ Repository extension to _Spring Data Common's_ Repository abstraction and infrastructure,
|
||||
you might even want to consider using _Spring Data for Pivotal GemFire's_
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/mapping/MappingPdxSerializer.html[MappingPdxSerializer],
|
||||
which uses a entity's mapping meta-data to determine data from the application domain object that will be serialized
|
||||
Pivotal GemFire serializes only application domain object types that you have specifically configured (registered)
|
||||
either by using Pivotal GemFire's
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[`ReflectionBasedAutoSerializer`],
|
||||
or specifically (and recommended) by using a "`custom`" Pivotal GemFire
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxSerializer.html[`PdxSerializer`]. If you use
|
||||
Spring Data for Pivotal GemFire's repository extension to Spring Data Common's repository abstraction and infrastructure,
|
||||
you might even want to consider using Spring Data for Pivotal GemFire's
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/mapping/MappingPdxSerializer.html[`MappingPdxSerializer`],
|
||||
which uses an entity's mapping meta-data to determine data from the application domain object that are serialized
|
||||
to the PDX instance.
|
||||
|
||||
What is less than apparent, though, is that Pivotal GemFire automatically handles Java Enum types regardless of whether they are
|
||||
explicitly configured or not (i.e. registered with a `ReflectionBasedAutoSerializer` using a regex pattern
|
||||
and the `classes` parameter, or are handled by a "custom" Pivotal GemFire `PdxSerializer`), despite the fact that Java Enums
|
||||
What is less than apparent, though, is that Pivotal GemFire automatically handles Java `Enum` types regardless of whether they are
|
||||
explicitly configured (that is, registered with a `ReflectionBasedAutoSerializer` using a regex pattern
|
||||
and the `classes` parameter or are handled by a "`custom`" Pivotal GemFire `PdxSerializer`), despite the fact that Java enumerations
|
||||
implement `java.io.Serializable`.
|
||||
|
||||
So, when a developer sets `pdx-read-serialized` to *true* on Pivotal GemFire Servers where the Pivotal GemFire Functions
|
||||
(including Spring Data for Pivotal GemFire Function annotated POJO classes) are registered, then the developer
|
||||
may encounter surprising behavior when invoking the Function `Execution`.
|
||||
So, when you set `pdx-read-serialized` to `true` on Pivotal GemFire servers where the Pivotal GemFire functions
|
||||
(including Spring Data for Pivotal GemFire function-annotated POJO classes) are registered, then you
|
||||
may encounter surprising behavior when invoking the function `Execution`.
|
||||
|
||||
What the developer may pass as arguments when invoking the Function is...
|
||||
You might pass the following arguments when invoking the function:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
orderProcessingFunctions.process(new Order(123, customer, Calendar.getInstance(), items), OrderSource.ONLINE, 400);
|
||||
----
|
||||
|
||||
But, what the Pivotal GemFire Function on the Server gets is...
|
||||
However, the Pivotal GemFire function on the server gets the following:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
process(regionData, order:PdxInstance, :PdxInstanceEnum, 400);
|
||||
----
|
||||
|
||||
The `Order` and `OrderSource` have been passed to the Function as
|
||||
The `Order` and `OrderSource` have been passed to the function as
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxInstance.html[PDX instances].
|
||||
Again, this is all because `pdx-read-serialized` is set to *true*, which may be necessary in cases where
|
||||
the Pivotal GemFire Servers are interacting with multiple different clients (e.g. Java, native clients, such as C++/C#, etc).
|
||||
Again, this all happens because `pdx-read-serialized` is set to `true`, which may be necessary in cases where
|
||||
the Pivotal GemFire servers interact with multiple different clients (for example, a combination of Java clients and native clients, such as C++, C#, and others).
|
||||
|
||||
This flies in the face of _Spring Data for Pivotal GemFire's_ "strongly-typed", Function annotated POJO class method signatures,
|
||||
as the developer is expecting application domain object types, not PDX serialized instances.
|
||||
This flies in the face of Spring Data for Pivotal GemFire's strongly-typed function-annotated POJO class method signatures,
|
||||
as you should reasonably expect application domain object types, not PDX serialized instances.
|
||||
|
||||
So, _Spring Data for Pivotal GemFire_ includes enhanced Function support to automatically convert method arguments passed to
|
||||
the Function that are of type PDX to the desired application domain object types defined by the Function method's
|
||||
Consequently, Spring Data for Pivotal GemFire includes enhanced function support to automatically convert method arguments
|
||||
type PDX to the desired application domain object types defined by the function method's
|
||||
parameter types.
|
||||
|
||||
However, this also requires the developer to explicitly register a Pivotal GemFire `PdxSerializer` on the Pivotal GemFire Servers
|
||||
where _Spring Data for Pivotal GemFire_ Function annotated POJOs are registered and used, e.g. ...
|
||||
However, this also requires you to explicitly register a Pivotal GemFire `PdxSerializer` on the Pivotal GemFire Servers
|
||||
where Spring Data for Pivotal GemFire function-annotated POJOs are registered and used, as the following example shows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -424,13 +419,13 @@ where _Spring Data for Pivotal GemFire_ Function annotated POJOs are registered
|
||||
<gfe:cache ... pdx-serializer-ref="customPdxSerializeer" pdx-read-serialized="true"/>
|
||||
----
|
||||
|
||||
Alternatively, a developer my use Pivotal GemFire's
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[ReflectionBasedAutoSerializer]
|
||||
for convenience. Of course, it is recommended that you use a "custom" `PdxSerializer` where possible to maintain
|
||||
finer grained control over your serialization strategy.
|
||||
Alternatively, you can use Pivotal GemFire's
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[`ReflectionBasedAutoSerializer`]
|
||||
for convenience. Of course, we recommend that, where possible, you use a custom `PdxSerializer` to maintain
|
||||
finer-grained control over your serialization strategy.
|
||||
|
||||
Finally, _Spring Data for Pivotal GemFire_ is careful not to convert your Function arguments if you treat your Function arguments
|
||||
generically, or as one of Pivotal GemFire's PDX types...
|
||||
Finally, Spring Data for Pivotal GemFire is careful not to convert your function arguments if you treat your function arguments
|
||||
generically or as one of Pivotal GemFire's PDX types, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -440,9 +435,9 @@ public Object genericFunction(String value, Object domainObject, PdxInstanceEnum
|
||||
}
|
||||
----
|
||||
|
||||
_Spring Data for Pivotal GemFire_ only converts PDX type data to the corresponding application domain types if and only if
|
||||
the corresponding application domain types are on the classpath the the Function annotated POJO method expects it.
|
||||
Spring Data for Pivotal GemFire converts PDX type data to the corresponding application domain types if and only if
|
||||
the corresponding application domain types are on the classpath and the function-annotated POJO method expects it.
|
||||
|
||||
For a good example of "custom", "composed" application-specific Pivotal GemFire `PdxSerializers` as well as appropriate
|
||||
POJO Function parameter type handling based on the method signatures, see Spring Data for Pivotal GemFire's
|
||||
https://github.com/spring-projects/spring-data-gemfire/blob/2.0.0.M2/src/test/java/org/springframework/data/gemfire/function/ClientCacheFunctionExecutionWithPdxIntegrationTest.java[ClientCacheFunctionExecutionWithPdxIntegrationTest] class.
|
||||
For a good example of custom, composed application-specific Pivotal GemFire `PdxSerializers` as well as appropriate
|
||||
POJO function parameter type handling based on the method signatures, see Spring Data for Pivotal GemFire's
|
||||
https://github.com/spring-projects/spring-data-gemfire/blob/2.0.0.M2/src/test/java/org/springframework/data/gemfire/function/ClientCacheFunctionExecutionWithPdxIntegrationTest.java[`ClientCacheFunctionExecutionWithPdxIntegrationTest`] class.
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
[[bootstrap:function]]
|
||||
= Configuring the Function Service
|
||||
|
||||
_Spring Data for Pivotal GemFire_ provides <<function-annotations,annotation>> support for implementing and registering
|
||||
Spring Data for Pivotal GemFire provides <<function-annotations,annotation>> support for implementing and registering
|
||||
Pivotal GemFire Functions.
|
||||
|
||||
_Spring Data for Pivotal GemFire_ also provides namespace support for registering Pivotal GemFire
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/Function.html[Functions]
|
||||
for remote Function execution.
|
||||
Spring Data for Pivotal GemFire also provides namespace support for registering Pivotal GemFire
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/execute/Function.html[functions]
|
||||
for remote function execution.
|
||||
|
||||
Please refer to Pivotal GemFire' http://geode.apache.org/docs/guide/11/developing/function_exec/chapter_overview.html[documentation]
|
||||
for more information on the Function execution framework.
|
||||
See Pivotal GemFire's http://geode.apache.org/docs/guide/11/developing/function_exec/chapter_overview.html[documentation]
|
||||
for more information on the function execution framework.
|
||||
|
||||
Pivotal GemFire Functions are declared as _Spring_ beans and must implement the `org.apache.geode.cache.execute.Function`
|
||||
Pivotal GemFire Functions are declared as Spring beans and must implement the `org.apache.geode.cache.execute.Function`
|
||||
interface or extend `org.apache.geode.cache.execute.FunctionAdapter`.
|
||||
|
||||
The namespace uses a familiar pattern to declare functions:
|
||||
The namespace uses a familiar pattern to declare functions, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
|
||||
@@ -2,15 +2,15 @@
|
||||
= Configuring WAN Gateways
|
||||
|
||||
WAN Gateways provide a way to synchronize Pivotal GemFire Distributed Systems across geographic areas.
|
||||
_Spring Data for Pivotal GemFire_ provides namespace support for configuring WAN Gateways as illustrated in the following examples.
|
||||
Spring Data for Pivotal GemFire provides namespace support for configuring WAN Gateways as illustrated in the following examples.
|
||||
|
||||
== WAN Configuration in Pivotal GemFire 7.0
|
||||
|
||||
In the example below, `GatewaySenders` are configured for a PARTITION Region by adding child elements to the Region
|
||||
(`gateway-sender` and `gateway-sender-ref`).
|
||||
In the following example, `GatewaySenders` are configured for a `PARTITION` region by adding child elements
|
||||
(`gateway-sender` and `gateway-sender-ref`) to the region.
|
||||
|
||||
A `GatewaySender` may register `EventFilters` and `TransportFilters`. Also shown below is an example configuration
|
||||
of an `AsyncEventQueue` which must also be wired into a Region (not shown).
|
||||
A `GatewaySender` may register `EventFilters` and `TransportFilters`. The following example also shows a sample configuration
|
||||
of an `AsyncEventQueue`, which must also be wired into a region (not shown):
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -48,8 +48,8 @@ of an `AsyncEventQueue` which must also be wired into a Region (not shown).
|
||||
<bean id="transport-filter" class="org.springframework.data.gemfire.example.AnotherTransportFilter"/>
|
||||
----
|
||||
|
||||
On the other end of a `GatewaySender` is a corresponding `GatewayReceiver` to receive Gateway events.
|
||||
The `GatewayReceiver` may also be configured with `EventFilters` and `TransportFilters`.
|
||||
On the other end of a `GatewaySender` is a corresponding `GatewayReceiver` to receive gateway events.
|
||||
The `GatewayReceiver` may also be configured with `EventFilters` and `TransportFilters`, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -60,6 +60,6 @@ The `GatewayReceiver` may also be configured with `EventFilters` and `TransportF
|
||||
</gfe:gateway-receiver>
|
||||
----
|
||||
|
||||
Please refer to the Pivotal GemFire
|
||||
See the Pivotal GemFire
|
||||
http://geode.apache.org/docs/guide/11/topologies_and_comm/multi_site_configuration/chapter_overview.html[documentation]
|
||||
for a detailed explanation of all the configuration options.
|
||||
|
||||
@@ -1,39 +1,37 @@
|
||||
[[gemfire-bootstrap]]
|
||||
= Bootstrapping a Spring ApplicationContext in Pivotal GemFire
|
||||
|
||||
== Introduction
|
||||
|
||||
Normally, a _Spring_-based application will <<bootstrap,bootstrap Pivotal GemFire>> using _Spring Data for Pivotal GemFire's.
|
||||
Just by specifying a `<gfe:cache/>` element using the _Spring Data for Pivotal GemFire_ XML namespace, a single, embedded Pivotal GemFire
|
||||
Normally, a Spring based application <<bootstrap,bootstraps Pivotal GemFire>> by using Spring Data for Pivotal GemFire's caching features.
|
||||
By specifying a `<gfe:cache/>` element that uses the Spring Data for Pivotal GemFire XML namespace, a single embedded Pivotal GemFire
|
||||
peer `Cache` instance is created and initialized with default settings in the same JVM process as your application.
|
||||
|
||||
However, it is sometimes necessary, perhaps a requirement imposed by your IT organization, that Pivotal GemFire be fully managed
|
||||
and operated using the provided Pivotal GemFire tool suite, such as with
|
||||
http://geode.apache.org/docs/guide/11/tools_modules/gfsh/chapter_overview.html[Gfsh]. By using _Gfsh_,
|
||||
Pivotal GemFire will bootstrap your _Spring_ application context rather than the other way around. Instead of
|
||||
an application server, or a Java main class using _Spring Boot_, whatever, Pivotal GemFire does the bootstrapping and will
|
||||
host your application.
|
||||
However, it is sometimes necessary (perhaps as a requirement imposed by your IT organization) that Pivotal GemFire be fully managed
|
||||
and operated by the provided Pivotal GemFire tool suite, perhaps with
|
||||
http://geode.apache.org/docs/guide/11/tools_modules/gfsh/chapter_overview.html[Gfsh]. By using Gfsh,
|
||||
Pivotal GemFire bootstraps your Spring application context rather than the other way around. Instead of
|
||||
an application server or a Java main class that uses Spring Boot, Pivotal GemFire does the bootstrapping and
|
||||
hosts your application.
|
||||
|
||||
Keep in mind, however, that Pivotal GemFire is not an application server. In addition, there are limitations to using
|
||||
this approach where Pivotal GemFire cache configuration is concerned.
|
||||
NOTE: Pivotal GemFire is not an application server. In addition, there are limitations to using
|
||||
this approach where the Pivotal GemFire cache configuration is concerned.
|
||||
|
||||
[[gemfire-bootstrap-gfsh]]
|
||||
== Using Pivotal GemFire to Bootstrap a Spring Context Started with Gfsh
|
||||
|
||||
In order to bootstrap a _Spring_ application context in Pivotal GemFire when starting a Pivotal GemFire Server process using _Gfsh_,
|
||||
a user must make use of Pivotal GemFire's
|
||||
http://geode.apache.org/docs/guide/11/basic_config/the_cache/setting_cache_initializer.html[Initalizer] functionality.
|
||||
An Initializer block can declare a callback application that is launched after the cache is initialized by Pivotal GemFire.
|
||||
In order to bootstrap a Spring application context in Pivotal GemFire when starting a Pivotal GemFire Server process by using Gfsh,
|
||||
you must use Pivotal GemFire's
|
||||
http://geode.apache.org/docs/guide/11/basic_config/the_cache/setting_cache_initializer.html[initalizer].
|
||||
An initializer block can declare a callback application that is launched after the cache is initialized by Pivotal GemFire.
|
||||
|
||||
An Initializer is declared within an
|
||||
http://geode.apache.org/docs/guide/11/reference/topics/cache_xml.html#initializer[initializer] element
|
||||
using a minimal snippet of Pivotal GemFire's native `cache.xml`. The `cache.xml` file is required in order to bootstrap
|
||||
the _Spring_ application context, much like a minimal snippet of _Spring_ XML config is needed to bootstrap
|
||||
a _Spring_ application context configured with component scanning (e.g. `<context:component-scan base-packages="..."/>`)
|
||||
An initializer is declared within an
|
||||
http://geode.apache.org/docs/guide/11/reference/topics/cache_xml.html#initializer[initializer] element by
|
||||
using a minimal snippet of Pivotal GemFire's native `cache.xml`. To bootstrap the Spring application context,
|
||||
the `cache.xml` file is required, in much the same way as a minimal snippet of Spring XML config is needed to bootstrap
|
||||
a Spring application context configured with component scanning (for example `<context:component-scan base-packages="..."/>`).
|
||||
|
||||
Fortunately, such an Initializer is already conveniently provided by the framework, the
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializer.html[SpringContextBootstrappingInitializer].
|
||||
A typical, yet very minimal configuration for this class inside Pivotal GemFires's `cache.xml` file will look like this:
|
||||
Fortunately, such an initializer is already conveniently provided by the framework: the
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/support/SpringContextBootstrappingInitializer.html[`SpringContextBootstrappingInitializer`].
|
||||
The following example shows a typical yet minimal configuration for this class inside Pivotal GemFires's `cache.xml` file:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -53,14 +51,14 @@ A typical, yet very minimal configuration for this class inside Pivotal GemFires
|
||||
</cache>
|
||||
----
|
||||
|
||||
The `SpringContextBootstrappingInitializer` class follows similar conventions as _Spring's_ `ContextLoaderListener`
|
||||
class used to bootstrap a _Spring_ application context inside a Web Application, where application context
|
||||
configuration files are specified with the `contextConfigLocations` Servlet Context Parameter.
|
||||
The `SpringContextBootstrappingInitializer` class follows conventions similar to Spring's `ContextLoaderListener`
|
||||
class, which is used to bootstrap a Spring application context inside a web application, where application context
|
||||
configuration files are specified with the `contextConfigLocations` servlet context parameter.
|
||||
|
||||
In addition, the `SpringContextBootstrappingInitializer` class can also be used with a `basePackages` parameter
|
||||
to specify a comma-separated list of base packages containing appropriately annotated application components
|
||||
that the _Spring_ container will search in order to find and create _Spring_ beans and other application components
|
||||
on the classpath:
|
||||
to specify a comma-separated list of base packages that contain appropriately annotated application components.
|
||||
The Spring container searches these components to find and create Spring beans and other application components
|
||||
on the classpath, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -80,8 +78,8 @@ on the classpath:
|
||||
</cache>
|
||||
----
|
||||
|
||||
Then, with a properly configured and constructed `CLASSPATH` along with `cache.xml` file shown above, specified as
|
||||
a command-line option when starting a Pivotal GemFire Server in _Gfsh_, the command-line would be:
|
||||
Then, with a properly configured and constructed `CLASSPATH` and `cache.xml` file (shown earlier) specified as
|
||||
a command-line option when starting a Pivotal GemFire Server in Gfsh, the command-line would be as follows:
|
||||
|
||||
[source]
|
||||
----
|
||||
@@ -90,38 +88,38 @@ gfsh>start server --name=Server1 --log-level=config ...
|
||||
--cache-xml-file="/path/to/geode/cache.xml"
|
||||
----
|
||||
|
||||
The `application-context.xml` can be any valid _Spring_ context configuration meta-data including all the SDG namespace
|
||||
elements. The only limitation with this approach is that a Pivotal GemFire cache cannot be configured using
|
||||
the _Spring Data for Pivotal GemFire_ namespace. In other words, none of the `<gfe:cache/>` element attributes,
|
||||
such as `cache-xml-location`, `properties-ref`, `critical-heap-percentage`, `pdx-serializer-ref`, `lock-lease`, etc,
|
||||
can be specified. If used, these attributes will be ignored.
|
||||
The `application-context.xml` can be any valid Spring context configuration metadata, including all of the SDG namespace
|
||||
elements. The only limitation with this approach is that a Pivotal GemFire cache cannot be configured by using
|
||||
the Spring Data for Pivotal GemFire namespace. In other words, none of the `<gfe:cache/>` element attributes
|
||||
(such as `cache-xml-location`, `properties-ref`, `critical-heap-percentage`, `pdx-serializer-ref`, `lock-lease`, and others)
|
||||
can be specified. If used, these attributes are ignored.
|
||||
|
||||
The reason for this is that Pivotal GemFire itself has already created an initialized the cache before the Initializer
|
||||
gets invoked. As such, the cache will already exist and since it is a "Singleton", it cannot be re-initialized
|
||||
or have any of it's configuration augmented.
|
||||
The reason for this is that Pivotal GemFire itself has already created and initialized the cache before the initializer
|
||||
gets invoked. As a result, the cache already exists and, since it is a "`singleton`", it cannot be re-initialized
|
||||
or have any of its configuration augmented.
|
||||
|
||||
[[gemfire-bootstrap-lazywiring]]
|
||||
== Lazy-Wiring Pivotal GemFire Components
|
||||
== Lazy-wiring Pivotal GemFire Components
|
||||
|
||||
_Spring Data for Pivotal GemFire_ already provides existing support for wiring Pivotal GemFire components, such as `CacheListeners`,
|
||||
`CacheLoaders`, `CacheWriters` and so on, that are declared and created by Pivotal GemFire in `cache.xml` using
|
||||
SDG's `WiringDeclarableSupport` class as described in <<apis:declarable:autowiring>>. However, this only works
|
||||
when _Spring_ is the one doing the bootstrapping (i.e. bootstrapping Pivotal GemFire).
|
||||
Spring Data for Pivotal GemFire already provides support for wiring Pivotal GemFire components (such as `CacheListeners`,
|
||||
`CacheLoaders`, `CacheWriters` and so on) that are declared and created by Pivotal GemFire in `cache.xml` by using
|
||||
SDG's `WiringDeclarableSupport` class, as described in <<apis:declarable:autowiring>>. However, this works only
|
||||
when Spring is the one doing the bootstrapping (that is, when Spring bootstraps Pivotal GemFire).
|
||||
|
||||
When your _Spring_ application context is bootstrapped by Pivotal GemFire, then these Pivotal GemFire application components go unnoticed
|
||||
since the _Spring_ application context does not even exist yet! The _Spring_ application context will not get created
|
||||
until Pivotal GemFire calls the Initializer block, which only occurs after all the other Pivotal GemFire components and configuration
|
||||
When your Spring application context is bootstrapped by Pivotal GemFire, these Pivotal GemFire application components go unnoticed,
|
||||
because the Spring application context does not yet exist. The Spring application context does not get created
|
||||
until Pivotal GemFire calls the initializer block, which only occurs after all the other Pivotal GemFire components and configuration
|
||||
have already been created and initialized.
|
||||
|
||||
So, in order to solve this problem, a new `LazyWiringDeclarableSupport` class was introduced that is, in a sense,
|
||||
_Spring_ application context aware. The intention of this abstract base class is that any implementing class
|
||||
will register itself to be configured by the _Spring_ container that will eventually be created by Pivotal GemFire
|
||||
once the Initializer is called. In essence, this give your Pivotal GemFire defined application components a chance
|
||||
to be configured and auto-wired with _Spring_ beans defined in the _Spring_ application context.
|
||||
To solve this problem, a new `LazyWiringDeclarableSupport` class was introduced. This new class is aware of the
|
||||
Spring application context. The intention of this abstract base class is that any implementing class
|
||||
register itself to be configured by the Spring container that is eventually be created by Pivotal GemFire
|
||||
once the initializer is called. In essence, this gives your Pivotal GemFire application components a chance
|
||||
to be configured and auto-wired with Spring beans defined in the Spring application context.
|
||||
|
||||
In order for your Pivotal GemFire application components to be auto-wired by the _Spring_ container, create an application class
|
||||
In order for your Pivotal GemFire application components to be auto-wired by the Spring container, you should create an application class
|
||||
that extends the `LazyWiringDeclarableSupport` and annotate any class member that needs to be provided as
|
||||
a _Spring_ bean dependency, similar to:
|
||||
a Spring bean dependency, similar to the following example:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -135,13 +133,15 @@ public class UserDataSourceCacheLoader extends LazyWiringDeclarableSupport
|
||||
}
|
||||
----
|
||||
|
||||
As implied in the `CacheLoader` example above, you might necessarily (although, rarely) have defined both
|
||||
a Region and `CacheListener` component in Pivotal GemFire `cache.xml`. The `CacheLoader` may need access to an application DAO,
|
||||
or perhaps a _Spring_ application context defined JDBC `DataSource` for loading `Users` into a Pivotal GemFire `REPLICATE` Region
|
||||
As implied in the `CacheLoader` example above, you might necessarily (though rarely) have defined both
|
||||
a region and a `CacheListener` component in Pivotal GemFire `cache.xml`. The `CacheLoader` may need access to an application DAO
|
||||
(or perhaps a JDBC `DataSource` defined in the Spring application context) for loading `Users` into a Pivotal GemFire `REPLICATE` region
|
||||
on start.
|
||||
|
||||
CAUTION: Be careful when mixing the different life-cycles of Pivotal GemFire and the _Spring_ Container together
|
||||
in this manner as not all use cases and scenarios are supported. The Pivotal GemFire `cache.xml` configuration would be
|
||||
CAUTION
|
||||
====
|
||||
Be careful when mixing the different life-cycles of Pivotal GemFire and the Spring Container together
|
||||
in this manner. Not all use cases and scenarios are supported. The Pivotal GemFire `cache.xml` configuration would be
|
||||
similar to the following (which comes from SDG's test suite):
|
||||
|
||||
[source,xml]
|
||||
@@ -173,3 +173,4 @@ similar to the following (which comes from SDG's test suite):
|
||||
|
||||
</cache>
|
||||
----
|
||||
====
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
[[bootstrap:indexing]]
|
||||
= Configuring an Index
|
||||
|
||||
Pivotal GemFire allows Indexes (or Indices) to be created on Region data to improve the performance of OQL queries.
|
||||
Pivotal GemFire allows indexes (also sometimes pluralized as indices) to be created on region data to improve the performance of OQL (Object Query Language) queries.
|
||||
|
||||
In _Spring Data for Pivotal GemFire_ (SDG), Indexes are declared with the `index` element:
|
||||
In Spring Data for Pivotal GemFire (SDG), indexes are declared with the `index` element, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:index id="myIndex" expression="someField" from="/SomeRegion" type="HASH"/>
|
||||
----
|
||||
|
||||
In _Spring Data for Pivotal GemFire's_ XML schema (a.k.a. SDG namespace), `Index` bean declarations are not bound to a _Region_,
|
||||
unlike Pivotal GemFire's native `cache.xml`. Rather, they are top-level elements just like `<gfe:cache>`. This allows
|
||||
a developer to declare any number of Indexes on any _Region_ whether they were just created or already exist,
|
||||
a significant improvement over Pivotal GemFire's native `cache.xml` format.
|
||||
In Spring Data for Pivotal GemFire's XML schema (also called the SDG namespace), `index` bean declarations are not bound to a region,
|
||||
unlike Pivotal GemFire's native `cache.xml`. Rather, they are top-level elements similar to `<gfe:cache>`. This lets
|
||||
you declare any number of indexes on any Region, whether they were just created or already exist -- a
|
||||
significant improvement over Pivotal GemFire's native `cache.xml` format.
|
||||
|
||||
An `Index` must have a name. A developer may give the `Index` an explicit name using the `name` attribute,
|
||||
otherwise the _bean name_ (i.e. value of the `id` attribute) of the `Index` bean definition is used as
|
||||
the `Index` name.
|
||||
An `Index` must have a name. You can give the `Index` an explicit name by using the `name` attribute.
|
||||
Otherwise, the bean name (that is, the value of the `id` attribute) of the `index` bean definition is used as
|
||||
the `index` name.
|
||||
|
||||
The `expression` and `from` clause form the main components of an `Index`, identifying the data to index
|
||||
(i.e. the _Region_ identified in the `from` clause) along with what criteria (i.e. `expression`) is used
|
||||
to index the data. The `expression` should be based on what application domain object fields are used
|
||||
in the predicate of application-defined OQL queries used to query and lookup the objects stored
|
||||
in the _Region_.
|
||||
The `expression` and `from` clause form the main components of an `index`, identifying the data to index
|
||||
(that is, the region identified in the `from` clause) along with what criteria (that is, `expression`) is used
|
||||
to index the data. The `expression` should be based on what application domain object fields are used
|
||||
in the predicate of application-defined OQL queries used to query and look up the objects stored
|
||||
in the Region.
|
||||
|
||||
For example, if I have a `Customer` that has a `lastName` property...
|
||||
Consider the following example, which has a `lastName` property:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -42,7 +42,7 @@ class Customer {
|
||||
}
|
||||
----
|
||||
|
||||
And, I also have an application defined SD[G] _Repository_ to query for `Customers`...
|
||||
Now consider the following example, which has an application-defined SDG repository to query for `Customer` objects:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -54,185 +54,184 @@ interface CustomerRepository extends GemfireRepository<Customer, Long> {
|
||||
}
|
||||
----
|
||||
|
||||
Then, the SD[G] _Repository_ finder/query method would result in the following OQL statement being executed...
|
||||
The SDG repository finder/query method results in the following OQL statement being run:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
SELECT * FROM /Customers c WHERE c.lastName = '$1'
|
||||
----
|
||||
|
||||
Therefore, I might want to create an `Index` like so...
|
||||
Therefore, you might want to create an `Index` with a statement similar to the following:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:index id="myIndex" name="CustomersLastNameIndex" expression="lastName" from="/Customers" type="HASH"/>
|
||||
----
|
||||
|
||||
The `from` clause must refer to a valid, existing _Region_ and is how an `Index` gets applied to a _Region_.
|
||||
This is *not* _Sprig Data Pivotal GemFire_ specific; this is a feature of Pivotal GemFire.
|
||||
The `from` clause must refer to a valid, existing region and is how an `index` gets applied to a region.
|
||||
This is not specific to Spring Data Pivotal GemFir. It is a feature of Pivotal GemFire.
|
||||
|
||||
The `Index` `type` maybe 1 of 3 enumerated values defined by _Spring Data for Pivotal GemFire's_
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/IndexType.html[IndexType]
|
||||
enumeration: `FUNCTIONAL`, `HASH` and `PRIMARY_KEY`.
|
||||
The `index` `type` may be one of three enumerated values defined by Spring Data for Pivotal GemFire's
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/IndexType.html[`IndexType`]
|
||||
enumeration: `FUNCTIONAL`, `HASH`, and `PRIMARY_KEY`.
|
||||
|
||||
Each of the enumerated values correspond to one of the http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html[QueryService]
|
||||
`create[|Key|Hash]Index` methods invoked when the actual `Index` is to be created (or "defined"; more on "defining"
|
||||
Indexes below). For instance, if the `IndexType` is `PRIMARY_KEY`, then the
|
||||
Each of the enumerated values corresponds to one of the http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html[`QueryService`]
|
||||
`create[|Key|Hash]Index` methods invoked when the actual `index` is to be created (or "`defined`" -- you can find more on "`defining`"
|
||||
indexes in the next section). For instance, if the `IndexType` is `PRIMARY_KEY`, then the
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#createKeyIndex-java.lang.String-java.lang.String-java.lang.String-[QueryService.createKeyIndex(..)]
|
||||
is invoked to create a `KEY` `Index`.
|
||||
|
||||
The default is `FUNCTIONAL` and results in one of the `QueryService.createIndex(..)` methods
|
||||
being invoked.
|
||||
|
||||
See the _Spring Data for Pivotal GemFire_ XML schema for a full set of options.
|
||||
See the Spring Data for Pivotal GemFire XML schema for a full set of options.
|
||||
|
||||
For more information on Indexing in Pivotal GemFire, see http://gemfire90.docs.pivotal.io/geode/developing/query_index/query_index.html[Working with Indexes]
|
||||
For more information on indexing in Pivotal GemFire, see "`http://gemfire90.docs.pivotal.io/geode/developing/query_index/query_index.html[Working with Indexes]`"
|
||||
in Pivotal GemFire's User Guide.
|
||||
|
||||
== Defining Indexes
|
||||
|
||||
In addition to creating Indexes upfront as `Index` bean definitions are processed by _Spring Data for Pivotal GemFire_
|
||||
on _Spring_ container initialization, you may also *define* all of your application Indexes prior to creating
|
||||
them by using the `define` attribute, like so...
|
||||
In addition to creating Indexes up front as `ndex` bean definitions are processed by Spring Data for Pivotal GemFire
|
||||
on Spring container initialization, you may also define all of your application indexes prior to creating
|
||||
them by using the `define` attribute, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
<gfe:index id="myDefinedIndex" expression="someField" from="/SomeRegion" define="true"/>
|
||||
----
|
||||
|
||||
When `define` is set to `true` (defaults to `false`), this will not actually create the `Index` right then and there.
|
||||
All "defined" Indexes are created all at once, when the _Spring_ `ApplicationContext` is "refreshed", or, that is,
|
||||
when a `ContextRefreshedEvent` is published by the _Spring_ container. _Spring Data for Pivotal GemFire_ registers itself as
|
||||
an `ApplicationListener` listening for the `ContextRefreshedEvent`. When fired, _Spring Data for Pivotal GemFire_ will call
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#createDefinedIndexes--[QueryService.createDefinedIndexes()].
|
||||
When `define` is set to `true` (it defaults to `false`), it does not actually create the `Index` at that moment.
|
||||
All "`defined`" Indexes are created all at once, when the Spring `ApplicationContext` is "`refreshed`" or, to put it differently,
|
||||
when a `ContextRefreshedEvent` is published by the Spring container. Spring Data for Pivotal GemFire registers itself as
|
||||
an `ApplicationListener` listening for the `ContextRefreshedEvent`. When fired, Spring Data for Pivotal GemFire calls
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#createDefinedIndexes[`QueryService.createDefinedIndexes()`].
|
||||
|
||||
Defining Indexes and creating them all at once helps promote speed and efficiency when creating Indexes.
|
||||
Defining indexes and creating them all at once boosts speed and efficiency when creating indexes.
|
||||
|
||||
See http://gemfire90.docs.pivotal.io/geode/developing/query_index/create_multiple_indexes.html[Creating Multiple Indexes at Once]
|
||||
See "`http://gemfire90.docs.pivotal.io/geode/developing/query_index/create_multiple_indexes.html[Creating Multiple Indexes at Once]`"
|
||||
for more details.
|
||||
|
||||
== `IgnoreIfExists` and `Override`
|
||||
|
||||
Two _Spring Data for Pivotal GemFire_ `Index` configuration options warrant special mention here: `ignoreIfExists` and `override`.
|
||||
Two Spring Data for Pivotal GemFire `Index` configuration options warrant special mention: `ignoreIfExists` and `override`.
|
||||
|
||||
These options correspond to the `ignore-if-exists` and `override` attributes on the `<gfe:index>` element
|
||||
in _Spring Data for Pivotal GemFire's_ XML schema, respectively.
|
||||
in Spring Data for Pivotal GemFire's XML schema, respectively.
|
||||
|
||||
WARNING: Make sure you absolutely understand what you are doing before using either of these options. These options can
|
||||
affect the performance and/or resources (e.g. memory) consumed by your application at runtime. As such, both of
|
||||
these options are disabled (i.e. set to `false`) in SDG by default.
|
||||
WARNING: Make sure you absolutely understand what you are doing before using either of these options. These options can
|
||||
affect the performance and resources (such as memory) consumed by your application at runtime. As a result, both of
|
||||
these options are disabled (set to `false`) in SDG by default.
|
||||
|
||||
NOTE: These options are only available in _Spring Data for Pivotal GemFire_ and exist to workaround known limitations
|
||||
with Pivotal GemFire; there are no equivalent options or functionality available in Pivotal GemFire itself.
|
||||
NOTE: These options are only available in Spring Data for Pivotal GemFire and exist to workaround known limitations
|
||||
with Pivotal GemFire. Pivotal GemFire has no equivalent options or functionality.
|
||||
|
||||
Each option significantly differs in behavior and entirely depends on the type of Pivotal GemFire `Index` _Exception_ thrown.
|
||||
This also means that neither option has any effect if a Pivotal GemFire Index-type _Exception_ is *not* thrown. These options
|
||||
are meant to specifically handle Pivotal GemFire `IndexExistsExceptions` and `IndexNameConflictExceptions`, which can occur
|
||||
for various, sometimes obscure reasons. But, in general...
|
||||
Each option significantly differs in behavior and entirely depends on the type of Pivotal GemFire `Index` exception thrown.
|
||||
This also means that neither option has any effect if a Pivotal GemFire Index-type exception is not thrown. These options
|
||||
are meant to specifically handle Pivotal GemFire `IndexExistsException` and `IndexNameConflictException` instances, which can occur
|
||||
for various, sometimes obscure reasons. The exceptions have the following causes:
|
||||
|
||||
* An http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/IndexExistsException.html[IndexExistsException]
|
||||
is thrown when there exists another `Index` with the same definition but different name when attempting to
|
||||
* An http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/IndexExistsException.html[`IndexExistsException`]
|
||||
is thrown when there exists another `Index` with the same definition but a different name when attempting to
|
||||
create an `Index`.
|
||||
|
||||
* An http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/IndexNameConflictException.html[IndexNameConflictException]
|
||||
* An http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/IndexNameConflictException.html[`IndexNameConflictException`]
|
||||
is thrown when there exists another `Index` with the same name but possibly different definition when attempting to
|
||||
create an `Index`.
|
||||
|
||||
_Spring Data for Pivotal GemFire's_ default behavior is to *_fail-fast_*, always! So, neither `Index` _Exception_ will be "handled"
|
||||
by default; these `Index` _Exceptions_ are simply wrapped in a SDG `GemfireIndexException` and rethrown. If you wish
|
||||
for _Spring Data for Pivotal GemFire_ to handle them for you, then you can set either of these `Index` bean definition options.
|
||||
Spring Data for Pivotal GemFire's default behavior is to fail-fast, always. So, neither `Index` _Exception_ are "`handled`"
|
||||
by default. These `Index` exceptions are wrapped in a SDG `GemfireIndexException` and rethrown. If you wish
|
||||
for Spring Data for Pivotal GemFire to handle them for you, you can set either of these `Index` bean definition options to `true`.
|
||||
|
||||
`IgnoreIfExists` always takes *precedence* over `Override`, primarily because it uses less resources given it returns
|
||||
the "existing" `Index` in both exceptional cases.
|
||||
`IgnoreIfExists` always takes precedence over `Override`, primarily because it uses fewer resources (because it returns
|
||||
the "`existing`" `index` in both exceptional cases).
|
||||
|
||||
=== `IgnoreIfExists` Behavior
|
||||
|
||||
When an `IndexExistsException` is thrown and `ignoreIfExists` is set to `true` (or `<gfe:index ignore-if-exists="true">`),
|
||||
then the `Index` that would have been created by this `Index` bean definition / declaration will be "*ignored*",
|
||||
and the "existing" `Index` will be returned.
|
||||
then the `index` that would have been created by this `index` bean definition or declaration is ignored,
|
||||
and the existing `Index` is returned.
|
||||
|
||||
There is very little consequence in returning the "existing" `Index` since the `Index` "definition" is the same,
|
||||
as deemed by Pivotal GemFire itself, *not* SDG.
|
||||
There is little consequence in returning the existing `index`, since the `Index` definition is the same,
|
||||
as determined by Pivotal GemFire itself, not SDG.
|
||||
|
||||
However, this also means that *no* `Index` with the "`name`" specified in your `Index` bean definition / declaration
|
||||
will "actually" exist from Pivotal GemFire's perspective either (i.e. with
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#getIndexes--[QueryService.getIndexes()]).
|
||||
Therefore, you should be careful when writing OQL query statements that use _Query Hints_, especially _Hints_ that refer
|
||||
to the application `Index` being "*ignored*". Those _Query Hints_ will need to be changed.
|
||||
However, this also means that no `index` with the "`name`" specified in your `Index` bean definition or declaration
|
||||
actually exists from Pivotal GemFire's perspective (that is, with
|
||||
http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#getIndexes[`QueryService.getIndexes()`]).
|
||||
Therefore, you should be careful when writing OQL query statements that use query hints, especially hints that refer
|
||||
to the application `Index` being ignored. Those query hints need to be changed.
|
||||
|
||||
Now, when an `IndexNameConflictException` is thrown and `ignoreIfExists` is set to `true` (or `<gfe:index ignore-if-exists="true">`),
|
||||
then the `Index` that would have been created by this `Index` bean definition / declaration will also be "*ignored*",
|
||||
and the "existing" Index will be returned, just like when an `IndexExistsException` is thrown.
|
||||
When an `IndexNameConflictException` is thrown and `ignoreIfExists` is set to `true` (or `<gfe:index ignore-if-exists="true">`),
|
||||
the `index` that would have been created by this `index` bean definition or declaration is also ignored,
|
||||
and the "existing" Index is returned, as when an `IndexExistsException` is thrown.
|
||||
|
||||
However, there is more risk in returning the "existing" `Index` and "*ignoring*" the application's definition
|
||||
of the `Index` when an `IndexNameConflictException` is thrown since, for a `IndexNameConflictException`, while the "names"
|
||||
of the conflicting Indexes are the same, the "definitions" could very well be different! This obviously could have
|
||||
implications for OQL queries specific to the application, where you would presume the Indexes were defined specifically
|
||||
with the application data access patterns and queries in mind. However, if like named Indexes differ in definition,
|
||||
this might not be the case. So, make sure you verify.
|
||||
However, there is more risk in returning the existing `index` and ignoring the application's definition
|
||||
of the `Index` when an `IndexNameConflictException` is thrown. For a `IndexNameConflictException`, while the names
|
||||
of the conflicting indexes are the same, the definitions could be different. This situation could have
|
||||
implications for OQL queries specific to the application, where you would presume the indexes were defined specifically
|
||||
with the application data access patterns and queries in mind. However, if like-named indexes differ in definition,
|
||||
this might not be the case. Consequently, you should verify your index names.
|
||||
|
||||
NOTE: SDG makes a best effort to inform the user when the `Index` being ignored is significantly different
|
||||
in its definition from the "existing" `Index`. However, in order for SDG to accomplish this, it must be able to "find"
|
||||
the existing `Index`, which is looked up using the Pivotal GemFire API (the only means available).
|
||||
in its definition from the existing `Index`. However, in order for SDG to accomplish this, it must be able to find
|
||||
the existing `Index`, which is looked up by using the Pivotal GemFire API (the only means available).
|
||||
|
||||
|
||||
=== `Override` Behavior
|
||||
|
||||
When an `IndexExistsException` is thrown and `override` is set to `true` (or `<gfe:index override="true">`), then
|
||||
the `Index` is effectively "_renamed_". Remember, `IndexExistsExceptions` are thrown when multiple Indexes exist,
|
||||
all having the same "definition" but different "names".
|
||||
When an `IndexExistsException` is thrown and `override` is set to `true` (or `<gfe:index override="true">`),
|
||||
the `Index` is effectively renamed. Remember, `IndexExistsExceptions` are thrown when multiple indexes exist that
|
||||
have the same definition but different names.
|
||||
|
||||
_Spring Data for Pivotal GemFire_ can only accomplish this using Pivotal GemFire's API, by first "_removing_" the "existing" `Index`
|
||||
and then "_recreating_" the `Index` with the *new* name. It is possible that either the remove or subsequent
|
||||
create invocation could fail. There is no way to execute both actions atomically and rollback this joint operation
|
||||
Spring Data for Pivotal GemFire can only accomplish this by using Pivotal GemFire's API, by first removing the existing `Index`
|
||||
and then recreating the `index` with the new name. It is possible that either the remove or subsequent
|
||||
create invocation could fail. There is no way to execute both actions atomically and rollback this joint operation
|
||||
if either fails.
|
||||
|
||||
However, if it succeeds, then you have the same problem as before with the "_ignoreIfExists_" option. Any existing OQL
|
||||
query statement using "_Query Hints_" referring to the old `Index` by name must be changed.
|
||||
However, if it succeeds, then you have the same problem as before with the `ignoreIfExists` option. Any existing OQL
|
||||
query statement using query hints that refer to the old `Index` by name must be changed.
|
||||
|
||||
Now, when an `IndexNameConflictException` is thrown and `override` is set to `true` (or `<gfe:index override="true">`),
|
||||
then potentially the "existing" `Index` will be "_re-defined_". I say "potentially", because it is possible for the
|
||||
"like-named", "existing" `Index` to have exactly the same definition and name when an `IndexNameConflictException`
|
||||
When an `IndexNameConflictException` is thrown and `override` is set to `true` (or `<gfe:index override="true">`),
|
||||
the existing `Index` can potentially be re-defined. We say "`potentially`" because it is possible for the
|
||||
like-named, existing `Index` to have exactly the same definition and name when an `IndexNameConflictException`
|
||||
is thrown.
|
||||
|
||||
If so, SDG is *smart* and will just return the "existing" Index as is, even on `override`. There is no harm in this
|
||||
since both the "name" and the "definition" are exactly the same. Of course, SDG can only accomplish this when
|
||||
SDG is able to "find" the "existing" `Index`, which is dependent on Pivotal GemFire's APIs. If it cannot find it,
|
||||
nothing happens and a SDG `GemfireIndexException` is thrown wrapping the `IndexNameConflictException`.
|
||||
If so, SDG is smart and returns the existing Index as is, even on `override`. There is no harm in this behavior,
|
||||
since both the name and the definition are exactly the same. Of course, SDG can only accomplish this when
|
||||
SDG is able to find the existing `Index`, which is dependent on Pivotal GemFire's APIs. If it cannot be found,
|
||||
nothing happens and a SDG `GemfireIndexException` is thrown that wraps the `IndexNameConflictException`.
|
||||
|
||||
However, when the "definition" of the "existing" `Index` is different, then SDG will attempt to "_recreate_" the `Index`
|
||||
using the `Index` definition specified in the `Index` bean definition /declaration. Make sure this is what you want
|
||||
However, when the definition of the existing `Index` is different, SDG attempts to re-create the `Index` by
|
||||
using the `Index` definition specified in the `Index` bean definition or declaration. Make sure this is what you want
|
||||
and make sure the `Index` definition matches your expectations and application requirements.
|
||||
|
||||
=== How does `IndexNameConflictExceptions` actually happen?
|
||||
=== How Does `IndexNameConflictExceptions` Actually Happen?
|
||||
|
||||
It is probably not all that uncommon for `IndexExistsExceptions` to be thrown, especially when
|
||||
multiple configuration sources are used to configure Pivotal GemFire (e.g. _Spring Data for Pivotal GemFire_, Pivotal GemFire _Cluster Config_,
|
||||
maybe Pivotal GemFire native `cache.xml`, the API, etc, etc). You should definitely prefer 1 configuration method here
|
||||
multiple configuration sources are used to configure Pivotal GemFire (Spring Data for Pivotal GemFire, Pivotal GemFire Cluster Config,
|
||||
Pivotal GemFire native `cache.xml`, the API, and so on). You should definitely prefer one configuration method
|
||||
and stick with it.
|
||||
|
||||
_However, when does an `IndexNameConflictException` get thrown?_
|
||||
However, when does an `IndexNameConflictException` get thrown?
|
||||
|
||||
One particular case is an `Index` defined on a `PARTITION` _Region_ (PR). When an `Index` is defined on
|
||||
a `PARTITION` _Region_ (e.g. "X"), Pivotal GemFire distributes the `Index` definition (and name) to other peer members
|
||||
in the cluster that also host the same `PARTITION` _Region_ (i.e. "X"). The distribution of this `Index` definition
|
||||
to and subsequent creation of this `Index` by peer members on a "need-to-know" basis (i.e. those hosting the same PR)
|
||||
One particular case is an `Index` defined on a `PARTITION` region (PR). When an `Index` is defined on
|
||||
a `PARTITION` region (for example, `X`), Pivotal GemFire distributes the `Index` definition (and name) to other peer members
|
||||
in the cluster that also host the same `PARTITION` region (that is, "X"). The distribution of this `Index` definition
|
||||
to and subsequent creation of this `Index` by peer members on a need-to-know basis (that is, those hosting the same PR)
|
||||
is performed asynchronously.
|
||||
|
||||
During this window of time, it is possible that these "pending" PR `Indexes` will not be identifiable by Pivotal GemFire,
|
||||
such as with a call to http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#getIndexes--[QueryService.getIndexes()]
|
||||
or with http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#getIndexes-org.apache.geode.cache.Region-[QueryService.getIndexes(:Region)],
|
||||
or even with http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#getIndex-org.apache.geode.cache.Region-java.lang.String-[QueryService.getIndex(:Region, indexName:String)].
|
||||
During this window of time, it is possible that these pending PR `Indexes` cannot be identified by Pivotal GemFire --
|
||||
such as with a call to http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#getIndexes[`QueryService.getIndexes()`]
|
||||
with http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#getIndexes-org.apache.geode.cache.Region[`QueryService.getIndexes(:Region)`],
|
||||
or even with http://gemfire-90-javadocs.docs.pivotal.io/org/apache/geode/cache/query/QueryService.html#getIndex-org.apache.geode.cache.Region-java.lang.String[`QueryService.getIndex(:Region, indexName:String)`].
|
||||
|
||||
As such, the only way for SDG or other Pivotal GemFire cache client applications (not involving _Spring_) to know for sure,
|
||||
is to just attempt to create the `Index`. If it fails with either an `IndexNameConflictException`,
|
||||
or even an `IndexExistsException`, then you will know. This is because the `QueryService` `Index` creation waits on
|
||||
"pending" `Index` definitions, where as the other Pivotal GemFire API calls do not.
|
||||
As a result, the only way for SDG or other Pivotal GemFire cache client applications (not involving Spring) to know for sure
|
||||
is to attempt to create the `Index`. If it fails with either an `IndexNameConflictException`
|
||||
or even an `IndexExistsException`, the application knows there is a problem. This is because the `QueryService` `Index` creation waits on
|
||||
pending `Index` definitions, whereas the other Pivotal GemFire API calls do not.
|
||||
|
||||
In any case, SDG makes a best effort and attempts to inform the user what has or is happening along with
|
||||
the corrective action. Given all Pivotal GemFire `QueryService.createIndex(..)` methods are synchronous, "blocking" operations,
|
||||
then the state of Pivotal GemFire should be consistent and accessible after either of these Index-type _Exceptions_ are thrown,
|
||||
in which case, SDG can inspect the state of the system and respond/act accordingly, based on the user's
|
||||
desired configuration.
|
||||
In any case, SDG makes a best effort and attempts to inform you what has happened or is happening and tell you
|
||||
the corrective action. Given that all Pivotal GemFire `QueryService.createIndex(..)` methods are synchronous, blocking operations,
|
||||
the state of Pivotal GemFire should be consistent and accessible after either of these index-type exceptions are thrown.
|
||||
Consequently, SDG can inspect the state of the system and act accordingly, based on your configuration.
|
||||
|
||||
In all other cases, SDG will simply *_fail-fast_*!
|
||||
In all other cases, SDG embraces a fail-fast strategy.
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
[[ref-introduction]]
|
||||
= Document Structure
|
||||
|
||||
The following chapters explain the core functionality offered by _Spring Data for Pivotal GemFire_.
|
||||
The following chapters explain the core functionality offered by Spring Data for Pivotal GemFire:
|
||||
|
||||
<<bootstrap>> describes the configuration support provided for configuring, initializing and accessing
|
||||
Pivotal GemFire Caches, Regions, and other related Distributed System components.
|
||||
* <<bootstrap>> describes the configuration support provided for configuring, initializing, and accessing
|
||||
Pivotal GemFire caches, regions, and related distributed system components.
|
||||
|
||||
<<apis>> explains the integration between the Pivotal GemFire APIs and the various data access features
|
||||
available in _Spring_, such as data access, exception translation, transaction management and caching.
|
||||
* <<apis>> explains the integration between the Pivotal GemFire APIs and the various data access features
|
||||
available in Spring, such as data access, exception translation, transaction management, and caching.
|
||||
|
||||
<<serialization>> describes enhancements to Pivotal GemFire's (de)serialization of managed objects.
|
||||
* <<serialization>> describes enhancements to Pivotal GemFire's serialization and deserialization of managed objects.
|
||||
|
||||
<<mapping>> describes persistence mapping for POJOs stored in Pivotal GemFire using _Spring Data_.
|
||||
* <<mapping>> describes persistence mapping for POJOs stored in Pivotal GemFire using Spring Data.
|
||||
|
||||
<<gemfire-repositories>> describes how to create and use _Spring Data Repositories_ to access data
|
||||
stored in Pivotal GemFire using basic CRUD and simple query operations.
|
||||
* <<gemfire-repositories>> describes how to create and use Spring Data Repositories to access data
|
||||
stored in Pivotal GemFire by using basic CRUD and simple query operations.
|
||||
|
||||
<<function-annotations>> describes how to create and use Pivotal GemFire Functions using Annotations
|
||||
* <<function-annotations>> describes how to create and use Pivotal GemFire functions by using annotations
|
||||
to perform distributed computations where the data lives.
|
||||
|
||||
<<apis:continuous-query>> describes how to use Pivotal GemFire's Continuous Query (CQ) functionality
|
||||
to process a stream of events based on interest defined and registered using a Pivotal GemFire OQL query.
|
||||
* <<apis:continuous-query>> describes how to use Pivotal GemFire's Continuous Query (CQ) functionality
|
||||
to process a stream of events based on interest defined and registered using a Pivotal GemFire OQL (Object Query Language) query.
|
||||
|
||||
<<gemfire-bootstrap>> describes how to bootstrap a _Spring_ `ApplicationContext` running in an Pivotal GemFire server
|
||||
using _Gfsh_.
|
||||
* <<gemfire-bootstrap>> describes how to bootstrap a Spring `ApplicationContext` running in an Pivotal GemFire server
|
||||
by using `Gfsh`.
|
||||
|
||||
<<samples>> describes the examples provided with the distribution to illustrate the various features
|
||||
available in _Spring Data for Pivotal GemFire_.
|
||||
* <<samples>> describes the examples provided with the distribution to illustrate the various features
|
||||
available in Spring Data for Pivotal GemFire.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
[[bootstrap:lucene]]
|
||||
= Apache Lucene Integration
|
||||
|
||||
https://pivotal.io/pivotal-gemfire[Pivotal GemFire] integrates with http://lucene.apache.org/[Apache Lucene] to allow developers
|
||||
to index and search on data stored in Pivotal GemFire using Lucene queries. Search-based queries also includes
|
||||
the capability to page through query results.
|
||||
https://pivotal.io/pivotal-gemfire[Pivotal GemFire] integrates with http://lucene.apache.org/[Apache Lucene] to let you
|
||||
index and search on data stored in Pivotal GemFire by using Lucene queries. Search-based queries also include
|
||||
the ability to page through query results.
|
||||
|
||||
Additionally, _Spring Data for Pivotal GemFire_ adds support for query projections based on _Spring Data Commons_
|
||||
Projection infrastructure. This feature enables the query results to be projected into first-class,
|
||||
application domain types as needed or required by the application use case.
|
||||
Additionally, Spring Data for Pivotal GemFire adds support for query projections based on the Spring Data Commons
|
||||
projection infrastructure. This feature lets the query results be projected into first-class
|
||||
application domain types as needed by the application use case.
|
||||
|
||||
However, a Lucene `Index` must be created before any Lucene search-based query can be ran. A `LuceneIndex`
|
||||
can be created in _Spring (Data for Pivotal GemFire)_ XML config like so...
|
||||
A Lucene `Index` must be created before any Lucene search-based query can be run. A `LuceneIndex`
|
||||
can be created in Spring (Data for Pivotal GemFire) XML config as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -18,8 +18,8 @@ can be created in _Spring (Data for Pivotal GemFire)_ XML config like so...
|
||||
----
|
||||
|
||||
Additionally, Apache Lucene allows the specification of
|
||||
http://lucene.apache.org/core/6_5_0/core/org/apache/lucene/analysis/Analyzer.html[Analyzers] per field
|
||||
and can be configured using...
|
||||
http://lucene.apache.org/core/6_5_0/core/org/apache/lucene/analysis/Analyzer.html[analyzers] per field
|
||||
and can be configured as shown in the following example:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -37,15 +37,15 @@ and can be configured using...
|
||||
</gfe:lucene-index>
|
||||
----
|
||||
|
||||
Of course, the `Map` can be specified as a top-level bean definition and referenced using the `ref` attribute
|
||||
in the nested `<gfe:field-analyzers>` element like this, `<gfe-field-analyzers ref="refToTopLevelMapBeanDefinition"/>`.
|
||||
The `Map` can be specified as a top-level bean definition and referenced by using the `ref` attribute
|
||||
in the nested `<gfe:field-analyzers>` element, as follows: `<gfe-field-analyzers ref="refToTopLevelMapBeanDefinition"/>`.
|
||||
|
||||
Spring Data for Pivotal GemFire's `LuceneIndexFactoryBean` API and SDG's XML namespace also allows the addition of a
|
||||
Spring Data for Pivotal GemFire's `LuceneIndexFactoryBean` API and SDG's XML namespace also let a
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/cache/lucene/LuceneSerializer.html[`org.apache.geode.cache.lucene.LuceneSerializer`]
|
||||
to be specified when creating the `LuceneIndex`. The `LuceneSerializer` is used to configure the way objects
|
||||
be specified when you create the `LuceneIndex`. The `LuceneSerializer` lets you configure the way objects
|
||||
are converted to Lucene documents for the index when the object is indexed.
|
||||
|
||||
To add an `LuceneSerializer` to the `LuceneIndex`, you only need to...
|
||||
The following example shows how to add an `LuceneSerializer` to the `LuceneIndex`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -56,7 +56,7 @@ To add an `LuceneSerializer` to the `LuceneIndex`, you only need to...
|
||||
</gfe:lucene-index>
|
||||
----
|
||||
|
||||
Of course, you may specify the `LuceneSerializer` as a anonymous, nested bean definition as well, like so...
|
||||
You can specify the `LuceneSerializer` as an anonymous, nested bean definition as well, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -67,8 +67,8 @@ Of course, you may specify the `LuceneSerializer` as a anonymous, nested bean de
|
||||
</gfe:lucene-index>
|
||||
----
|
||||
|
||||
Alternatively, a developer may declare or define a `LuceneIndex` in Spring Java config,
|
||||
inside a `@Configuration` class with...
|
||||
Alternatively, you can declare or define a `LuceneIndex` in Spring Java config,
|
||||
inside a `@Configuration` class, as the following example shows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -108,39 +108,39 @@ CustomLuceneSerializer myLuceneSerialier() {
|
||||
|
||||
There are a few limitations of Pivotal GemFire's, Apache Lucene integration and support.
|
||||
|
||||
First, a `LuceneIndex` can only be created on an Pivotal GemFire `PARTITION` Region.
|
||||
First, a `LuceneIndex` can only be created on a Pivotal GemFire `PARTITION` Region.
|
||||
|
||||
Second, all `LuceneIndexes` must be created before the Region to which the `LuceneIndex` applies.
|
||||
Second, all `LuceneIndexes` must be created before the region to which the `LuceneIndex` applies.
|
||||
|
||||
NOTE: To help ensure that all declared `LuceneIndexes` defined in a Spring context are created before the Regions
|
||||
NOTE: To help ensure that all declared `LuceneIndexes` defined in a Spring context are created before the regions
|
||||
on which they apply, SDG includes the `org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor`.
|
||||
You may register this Spring https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/beans/factory/config/BeanFactoryPostProcessor.html[`BeanFactoryPostProcessor`]
|
||||
in XML config using `<bean class="org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor"/>`
|
||||
in XML config by using `<bean class="org.springframework.data.gemfire.config.support.LuceneIndexRegionBeanFactoryPostProcessor"/>`
|
||||
The `o.s.d.g.config.support.LuceneIndexRegionBeanFactoryPostProcessor` may only be used when using SDG XML config.
|
||||
More details about Spring's `BeanFactoryPostProcessors` can be found https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-factory-extension-factory-postprocessors[here].
|
||||
|
||||
It is possible that these Pivotal GemFire restrictions will not apply in a future release which is why
|
||||
the SDG `LuceneIndexFactoryBean` API takes a reference to the Region directly as well, rather than just the Region path.
|
||||
the SDG `LuceneIndexFactoryBean` API takes a reference to the region directly as well, rather than just the region path.
|
||||
|
||||
This is more ideal if think about the case in which users may want to define a `LuceneIndex` on an existing Region
|
||||
with data at a later point during the application's lifecycle and as requirements demand. Where possible, SDG strives
|
||||
to adhere to strongly-typed objects. However, for the time being, you must use the `regionPath` property
|
||||
to specify the Region to which the `LuceneIndex` will be applied.
|
||||
This is more ideal when you want to define a `LuceneIndex` on an existing region
|
||||
with data at a later point during the application's lifecycle and as requirements demand. Where possible, SDG strives
|
||||
to adhere to strongly-typed objects. However, for the time being, you must use the `regionPath` property
|
||||
to specify the region to which the `LuceneIndex` is applied.
|
||||
|
||||
NOTE: Additional, in the example above, you will notice the presence of Spring's `@DependsOn` annotation
|
||||
on the "Books" Region bean definition. This is used to create a dependency from the "Books" Region bean
|
||||
to the "bookTitleIndex" LuceneIndex bean definition ensuring that the `LuceneIndex` will be created before
|
||||
the Region on which it applies.
|
||||
NOTE: Additionally, in the preceding example, note the presence of Spring's `@DependsOn` annotation
|
||||
on the `Books` region bean definition. This creates a dependency from the `Books` region bean
|
||||
to the `bookTitleIndex` `LuceneIndex` bean definition, ensuring that the `LuceneIndex` is created before
|
||||
the region on which it applies.
|
||||
|
||||
Now that we have a `LuceneIndex` we can perform Lucene based data access operations, such as queries.
|
||||
Now that we have a `LuceneIndex`, we can perform Lucene-based data access operations, such as queries.
|
||||
|
||||
== Lucene Template Data Accessors
|
||||
|
||||
_Spring Data for Pivotal GemFire_ provides 2 primary templates for Lucene data access operations, depending on
|
||||
Spring Data for Pivotal GemFire provides two primary templates for Lucene data access operations, depending on
|
||||
how low of a level your application is prepared to deal with.
|
||||
|
||||
The `LuceneOperations` interface defines query operations using Pivotal GemFire
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/cache/lucene/package-summary.html[Lucene types].
|
||||
The `LuceneOperations` interface defines query operations by using Pivotal GemFire
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/cache/lucene/package-summary.html[Lucene types], which are defined in the following interface definition:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -173,16 +173,17 @@ NOTE: The `[, int resultLimit]` indicates that the `resultLimit` parameter is op
|
||||
The operations in the `LuceneOperations` interface match the operations provided by the Pivotal GemFire's
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/cache/lucene/LuceneQuery.html[LuceneQuery] interface.
|
||||
However, SDG has the added value of translating proprietary Pivotal GemFire or Apache Lucene `Exceptions`
|
||||
into _Spring's_ highly consistent and expressive DAO
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#dao-exceptions[Exception Hierarchy],
|
||||
particularly as many modern data access operations involve more than single store or repository.
|
||||
into Spring's highly consistent and expressive DAO
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#dao-exceptions[exception hierarchy],
|
||||
particularly as many modern data access operations involve more than one store or repository.
|
||||
|
||||
Additionally, SDG's `LuceneOperations` interface can shield your application from interface breaking changes
|
||||
introduced by the underlying Pivotal GemFire or Apache Lucene APIs when they do and will occur.
|
||||
Additionally, SDG's `LuceneOperations` interface can shield your application from interface-breaking changes
|
||||
introduced by the underlying Pivotal GemFire or Apache Lucene APIs when they occur.
|
||||
|
||||
However, it would be remorse to only offer a Lucene Data Access Object (DAO) that only uses Pivotal GemFire
|
||||
and Apache Lucene data types (e.g. Pivotal GemFire's `LuceneResultStruct`), therefore SDG gives you the
|
||||
However, it would be sad to offer a Lucene Data Access Object (DAO) that only uses Pivotal GemFire
|
||||
and Apache Lucene data types (such as Pivotal GemFire's `LuceneResultStruct`). Therefore, SDG gives you the
|
||||
`ProjectingLuceneOperations` interface to remedy these important application concerns.
|
||||
The following listing shows the `ProjectingLuceneOperations` interface definition:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -198,15 +199,15 @@ public interface ProjectingLuceneOperations {
|
||||
}
|
||||
----
|
||||
|
||||
The `ProjectingLuceneOperations` interface primarily uses application domain object types allowing you to work with
|
||||
your application data. The `query` method variants accept a projection type and the template applies the query results
|
||||
to instances of the given projection type using the _Spring Data Commons_ Projection infrastructure.
|
||||
The `ProjectingLuceneOperations` interface primarily uses application domain object types that let you work with
|
||||
your application data. The `query` method variants accept a projection type, and the template applies the query results
|
||||
to instances of the given projection type by using the Spring Data Commons Projection infrastructure.
|
||||
|
||||
Additionally, the template wraps the paged Lucene query results in an instance of the _Spring Data Commons_
|
||||
`Page` abstraction. The same projection logic can still be applied to the results in the page and are lazily projected
|
||||
Additionally, the template wraps the paged Lucene query results in an instance of the Spring Data Commons
|
||||
`Page` abstraction. The same projection logic can still be applied to the results in the page and are lazily projected
|
||||
as each page in the collection is accessed.
|
||||
|
||||
By way of example, suppose I have a class representing a `Person` like so...
|
||||
By way of example, suppose you have a class representing a `Person`, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -227,7 +228,7 @@ class Person {
|
||||
}
|
||||
----
|
||||
|
||||
Additionally, I might have a single interface to represent people as `Customers` depending on my application view...
|
||||
Additionally, you might have a single interface to represent people as `Customers`, depending on your application view, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -256,48 +257,48 @@ LuceneIndexFactoryBean personLastNameIndex(Pivotal GemFireCache gemfireCache) {
|
||||
}
|
||||
----
|
||||
|
||||
Then it is a simple matter to query for people as either `Person` objects...
|
||||
Then you could query for people as `Person` objects, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
List<Person> people = luceneTemplate.query("lastName: D*", "lastName", Person.class);
|
||||
----
|
||||
|
||||
Or as a `Page` of type `Customer`...
|
||||
Alternatively, you could query for a `Page` of type `Customer`, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
Page<Customer> customers = luceneTemplate.query("lastName: D*", "lastName", 100, 20, Customer.class);
|
||||
----
|
||||
|
||||
The `Page` can then be used to fetch individual pages of the results...
|
||||
The `Page` can then be used to fetch individual pages of the results, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
List<Customer> firstPage = customers.getContent();
|
||||
----
|
||||
|
||||
Conveniently, the _Spring Data Commons_ `Page` interface implements `java.lang.Iterable<T>` too making it very easy
|
||||
Conveniently, the Spring Data Commons `Page` interface also implements `java.lang.Iterable<T>`, making it easy
|
||||
to iterate over the contents.
|
||||
|
||||
The only restriction to the _Spring Data Commons_ Projection infrastructure is that the projection type
|
||||
must be an interface. However, it is possible to extend the provided, out-of-the-box (OOTB)
|
||||
The only restriction to the Spring Data Commons projection infrastructure is that the projection type
|
||||
must be an interface. However, it is possible to extend the provided
|
||||
SDC Projection infrastructure and provide a custom
|
||||
http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/projection/ProjectionFactory.html[ProjectionFactory]
|
||||
http://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/projection/ProjectionFactory.html[`ProjectionFactory`]
|
||||
that uses https://github.com/cglib/cglib[CGLIB] to generate proxy classes as the projected entity.
|
||||
|
||||
A custom `ProjectionFactory` can be set on a Lucene template using `setProjectionFactory(:ProjectionFactory)`.
|
||||
You can use `setProjectionFactory(:ProjectionFactory)` to set a custom `ProjectionFactory` on a Lucene template.
|
||||
|
||||
== Annotation configuration support
|
||||
== Annotation Configuration Support
|
||||
|
||||
Finally, _Spring Data for Pivotal GemFire_ provides Annotation configuration support for `LuceneIndexes`.
|
||||
Eventually, the SDG Lucene support will find its way into the _Repository_ infrastructure extension for Pivotal GemFire
|
||||
so that Lucene queries can be expressed as methods on an application `Repository` interface, much like the
|
||||
Finally, Spring Data for Pivotal GemFire provides annotation configuration support for `LuceneIndexes`.
|
||||
Eventually, the SDG Lucene support finds its way into the repository infrastructure extension for Pivotal GemFire
|
||||
so that Lucene queries can be expressed as methods on an application `Repository` interface, in much the same way as the
|
||||
http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/#gemfire-repositories.executing-queries[OQL support]
|
||||
today.
|
||||
works today.
|
||||
|
||||
However, in the meantime, if you want to conveniently express `LuceneIndexes`, you can do so directly on
|
||||
your application domain objects like so...
|
||||
your application domain objects, as the following example shows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -318,8 +319,8 @@ class Person {
|
||||
}
|
||||
----
|
||||
|
||||
You must use SDG's Annotation configuration support along with the `@EnableEntityDefineRegions` and `@EnableIndexing`
|
||||
Annotations to enable this feature...
|
||||
To enable this feature, you must use SDG's Annotation configuration support and the `@EnableEntityDefineRegions` and `@EnableIndexing`
|
||||
Annotations, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -332,12 +333,10 @@ class ApplicationConfiguration {
|
||||
}
|
||||
----
|
||||
|
||||
NOTE: Keep in mind that `LuceneIndexes` can only be created on Apache Geode Servers since `LuceneIndexes` only apply
|
||||
to `PARTTION` Regions.
|
||||
NOTE: `LuceneIndexes` can be created only on Apache Geode Servers since `LuceneIndexes` only apply
|
||||
to `PARTITION` Regions.
|
||||
|
||||
Given our definition of the `Person` class above, the SDG Annotation configuration support
|
||||
will find the `Person` entity class definition, determine that people will be stored in
|
||||
a `PARTITION` Region called "People" and that the `Person` will have an OQL `Index` on `birthDate`
|
||||
Given our earlier definition of the `Person` class, the SDG annotation configuration support
|
||||
finds the `Person` entity class definition and determines that people are stored in
|
||||
a `PARTITION` region called `People` and that the `Person` has an OQL `Index` on `birthDate`
|
||||
along with a `LuceneIndex` on `lastName`.
|
||||
|
||||
More will be described with this feature in subsequent releases.
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
[[mapping]]
|
||||
= POJO mapping
|
||||
= POJO Mapping
|
||||
|
||||
This section covers:
|
||||
|
||||
* <<mapping.entities>>
|
||||
* <<mapping.repositories>>
|
||||
* The <<Mapping PDX Serializer>>
|
||||
|
||||
[[mapping.entities]]
|
||||
== Entity Mapping
|
||||
|
||||
_Spring Data for Pivotal GemFire_ provides support to map entities that will be stored in a Region
|
||||
in the Geode In-Memory Data Grid.
|
||||
|
||||
The mapping metadata is defined using annotations on application domain classes just like this:
|
||||
Spring Data for Pivotal GemFire provides support to map entities that are stored in a region in the Geode In-Memory Data Grid.
|
||||
The mapping metadata is defined by using annotations on application domain classes, as the following example shows:
|
||||
|
||||
.Mapping a domain class to a Pivotal GemFire Region
|
||||
====
|
||||
@@ -31,16 +35,14 @@ public class Person {
|
||||
----
|
||||
====
|
||||
|
||||
The first thing you notice here is the `@Region` annotation that can be used to customize the Region
|
||||
in which an instance of the `Person` class is stored. The `@Id` annotation can be used to annotate the property
|
||||
that shall be used as the cache (Region) key, identifying the Region entry. The `@PersistenceConstructor` annotation
|
||||
helps to disambiguate multiple, potentially available constructors taking parameters and explicitly marking
|
||||
The `@Region` annotation can be used to customize the region
|
||||
in which an instance of the `Person` class is stored. The `@Id` annotation can be used to annotate the property
|
||||
that should be used as the cache (region) key, identifying the region entry. The `@PersistenceConstructor` annotation
|
||||
helps to disambiguate multiple potentially available constructors, taking parameters and explicitly marking
|
||||
the constructor annotated as the constructor to be used to construct entities. In an application domain class with no
|
||||
or only a single constructor you can omit the annotation.
|
||||
or only a single constructor, you can omit the annotation.
|
||||
|
||||
In addition to storing entities in top-level Regions, entities can be stored in Sub-Regions as well.
|
||||
|
||||
For instance:
|
||||
In addition to storing entities in top-level regions, entities can be stored in Sub-Regions as well, as the following example shows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -55,39 +57,37 @@ public class Guest extends User {
|
||||
}
|
||||
----
|
||||
|
||||
Be sure to use the full-path of the Pivotal GemFire Region, as defined with the _Spring Data for Pivotal GemFire_ XML namespace
|
||||
Be sure to use the full path of the Pivotal GemFire region, as defined with the Spring Data for Pivotal GemFire XML namespace by
|
||||
using the `id` or `name` attributes of the `<*-region>` element.
|
||||
|
||||
[[mapping.entities.region]]
|
||||
=== Entity Mapping by Region Type
|
||||
|
||||
In addition to the `@Region` annotation, _Spring Data for Pivotal GemFire_ also recognizes the Region type-specific
|
||||
mapping annotations: `@ClientRegion`, `@LocalRegion`, `@PartitionRegion` and `@ReplicateRegion`.
|
||||
In addition to the `@Region` annotation, Spring Data for Pivotal GemFire also recognizes the region type-specific
|
||||
mapping annotations: `@ClientRegion`, `@LocalRegion`, `@PartitionRegion`, and `@ReplicateRegion`.
|
||||
|
||||
Functionally, these annotations are treated exactly the same as the generic `@Region` annotation in the SDG
|
||||
mapping infrastructure. However, these additional mapping annotations are useful in _Spring Data for Pivotal GemFire's`
|
||||
Annotation configuration model. When combined with the `@EnableEntityDefinedRegions` configuration annotation
|
||||
on _Spring_ `@Configuration` annotated class, it is possible to generate Regions in the local cache, whether
|
||||
mapping infrastructure. However, these additional mapping annotations are useful in Spring Data for Pivotal GemFire's
|
||||
annotation configuration model. When combined with the `@EnableEntityDefinedRegions` configuration annotation
|
||||
on a Spring `@Configuration` annotated class, it is possible to generate regions in the local cache, whether
|
||||
the application is a client or peer.
|
||||
|
||||
These annotations allow you, the developer, to be more specific about what type of Region that your application
|
||||
entity class should be mapped to, and also has an impact on the data management policies of the Region
|
||||
(e.g. partition (a.k.a. sharding) vs. just replicating data).
|
||||
These annotations let you be more specific about what type of region your application
|
||||
entity class should be mapped to and also have an impact on the data management policies of the region
|
||||
(for example, partition -- also known as sharding -- versus replicating data).
|
||||
|
||||
Using these Region type-specific mapping annotations with the SDG Annotation config model saves you from having to
|
||||
explicitly define these Regions in config.
|
||||
|
||||
The details of the new Annotation configuration model will be discussed in more detail in a subsequent releaase.
|
||||
Using these region type-specific mapping annotations with the SDG Annotation config model saves you from having to
|
||||
explicitly define these regions in configuration.
|
||||
|
||||
[[mapping.repositories]]
|
||||
=== Repository Mapping
|
||||
== Repository Mapping
|
||||
|
||||
As an alternative to specifying the Region in which the entity will be stored using the `@Region` annotation
|
||||
As an alternative to specifying the region in which the entity is stored by using the `@Region` annotation
|
||||
on the entity class, you can also specify the `@Region` annotation on the entity's `Repository`.
|
||||
See <<gemfire-repositories>> for more details.
|
||||
|
||||
However, let's say you want to store a `Person` in multiple Pivotal GemFire Regions (e.g. `People` and `Customers`),
|
||||
then you can define your corresponding `Repository` interface extensions like so:
|
||||
However, suppose you want to store a `Person` record in multiple Pivotal GemFire Regions (for example, `People` and `Customers`).
|
||||
Then you can define your corresponding `Repository` interface extensions as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -102,7 +102,7 @@ public interface CustomerRepository extends GemfireRepository<Person, String> {
|
||||
}
|
||||
----
|
||||
|
||||
Then, using each Repository individually, you can store the entity in multiple Pivotal GemFire Regions.
|
||||
Then, using each Repository individually, you can store the entity in multiple Pivotal GemFire Regions, as the following example shows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -120,24 +120,24 @@ class CustomerService {
|
||||
}
|
||||
----
|
||||
|
||||
It is not difficult to imagine wrapping the `update` service method in a _Spring_ managed transaction,
|
||||
You can wrap the `update` service method in a Spring managed transaction,
|
||||
either as a local cache transaction or a global transaction.
|
||||
|
||||
[[mapping.pdx-serializer]]
|
||||
== Mapping PDX Serializer
|
||||
|
||||
_Spring Data for Pivotal GemFire_ provides a custom
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxSerializer.html[PdxSerializer] implementation
|
||||
Spring Data for Pivotal GemFire provides a custom
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxSerializer.html[`PdxSerializer`] implementation
|
||||
that uses the mapping information to customize entity serialization.
|
||||
|
||||
Beyond that, it also allows customizing entity instantiation by using the Spring Data `EntityInstantiator` abstraction.
|
||||
By default, the serializer uses a `ReflectionEntityInstantiator` that will use the persistence constructor of
|
||||
the mapped entity (either the default constructor, a singly declared constructor or an explicitly annotated constructor
|
||||
annotated with the `@PersistenceConstructor` annotation).
|
||||
It also lets you customize entity instantiation by using the Spring Data `EntityInstantiator` abstraction.
|
||||
By default, the serializer uses a `ReflectionEntityInstantiator` that uses the persistence constructor of
|
||||
the mapped entity (the default constructor, a singly declared constructor, or a constructor
|
||||
explicitly annotated with `@PersistenceConstructor`).
|
||||
|
||||
To provide arguments for constructor parameters, the serializer will read fields with the named constructor parameter,
|
||||
To provide arguments for constructor parameters, the serializer reads fields with the named constructor parameter,
|
||||
explicitly specified using Spring's `@Value` annotation, from the supplied
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxReader.html[PdxReader].
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxReader.html[`PdxReader`], as shown in the following example:
|
||||
|
||||
.Using `@Value` on entity constructor parameters
|
||||
====
|
||||
@@ -145,29 +145,29 @@ http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxReader.html[P
|
||||
----
|
||||
public class Person {
|
||||
|
||||
public Person(@Value("#root.foo") String firstName, @Value("bean") String lastName) {
|
||||
public Person(@Value("#root.thing") String firstName, @Value("bean") String lastName) {
|
||||
// …
|
||||
}
|
||||
}
|
||||
----
|
||||
====
|
||||
|
||||
An entity class annotated in this way will have the field `foo` read from the `PdxReader` and passed as the value
|
||||
for the constructor parameter, `firstname`. The value for `lastName` will be a _Spring_ bean with the name `bean`.
|
||||
An entity class annotated in this way has the `thing` field read from the `PdxReader` and passed as the value
|
||||
for the constructor parameter, `firstname`. The value for `lastName` is a Spring bean with the name `bean`.
|
||||
|
||||
In addition to the custom instantiation logic and strategy provided by `EntityInstantiators`
|
||||
the `MappingPdxSerializer` also provides capabilities above and beyond even Pivotal GemFire's own
|
||||
In addition to the custom instantiation logic and strategy provided by `EntityInstantiators`,
|
||||
the `MappingPdxSerializer` also provides capabilities beyond Pivotal GemFire's own
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[`ReflectionBasedAutoSerializer`].
|
||||
|
||||
While Pivotal GemFire's `ReflectionBasedAutoSerializer` conveniently uses Java Reflection to populate entities as well as
|
||||
use _Regular Expressions_ to identify types that should be handled (de/serialized) by the `ReflectionBasedAutoSerializer`,
|
||||
While Pivotal GemFire's `ReflectionBasedAutoSerializer` conveniently uses Java reflection to populate entities and
|
||||
uses regular expressions to identify types that should be handled (serialized and deserialized) by the `ReflectionBasedAutoSerializer`,
|
||||
it cannot, unlike `MappingPdxSerializer`, perform the following:
|
||||
|
||||
1. Register custom `PdxSerializer` objects per entity field/property names and/or types.
|
||||
2. Conveniently identifies ID properties.
|
||||
3. Automatically handles *read-only* properties.
|
||||
4. Automatically handles *transient* properties.
|
||||
5. Allows more robust *type filtering* in a `null`-safe manner (e.g. not limited to only expressing types via Regex).
|
||||
* Register custom `PdxSerializer` objects per entity field and property names and types.
|
||||
* Conveniently identifies ID properties.
|
||||
* Automatically handles read-only properties.
|
||||
* Automatically handles transient properties.
|
||||
* Allows more robust type filtering in a `null`-safe manner (for example, not limited to only expressing types with regex).
|
||||
|
||||
We now explore each feature of the `MappingPdxSerializer` in a bit more detail.
|
||||
|
||||
@@ -175,9 +175,9 @@ We now explore each feature of the `MappingPdxSerializer` in a bit more detail.
|
||||
=== Custom PdxSerializer Registration
|
||||
|
||||
The `MappingPdxSerializer` gives you the ability to register custom `PdxSerializers` based on an entity's
|
||||
field/property names and/or types.
|
||||
field and property names and types.
|
||||
|
||||
For instance, suppose you have defined an entity type modeling a `User` as...
|
||||
For instance, suppose you have defined an entity type modeling a `User` as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -193,12 +193,12 @@ public class User {
|
||||
}
|
||||
----
|
||||
|
||||
While the `User's` "name" probably does not require any special logic to serialize the value for name, serializing
|
||||
the `Password` might require additional logic in order to handle the sensitive nature of the field or property.
|
||||
While the user's name probably does not require any special logic to serialize the value, serializing
|
||||
the password might require additional logic to handle the sensitive nature of the field or property.
|
||||
|
||||
Perhaps you want to protect the password when sending the value over the network, between a client and a server,
|
||||
and you only want to store the _Salted Hash_. When using the `MappingPdxSerializer` you can register
|
||||
a custom `PdxSerializer` to handle the `User's` `Password`, like so...
|
||||
and you only want to store the salted hash. When using the `MappingPdxSerializer`, you can register
|
||||
a custom `PdxSerializer` to handle the user's password, as follows:
|
||||
|
||||
.Registering custom `PdxSerializers` by POJO field/property type
|
||||
====
|
||||
@@ -212,12 +212,12 @@ mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
|
||||
----
|
||||
|
||||
After registering the application-defined `SaltedHashPasswordPdxSerializer` instance with the `Password`
|
||||
application domain model type, the `MappingPdxSerializer` will consult the custom `PdxSerializer` to
|
||||
de/serialize *all* `Password` objects regardless of the containing object (e.g. `User`).
|
||||
application domain model type, the `MappingPdxSerializer` consults the custom `PdxSerializer` to
|
||||
serialize and deserialize all `Password` objects regardless of the containing object (for example, `User`).
|
||||
|
||||
However, suppose you only want to customize the serialization of `Passwords` on `User` objects, specifically.
|
||||
Then, you can register the custom `PdxSerializer` for the `User` type only by specifying the fully-qualified
|
||||
name of the `Class's` field/property. For example:
|
||||
However, suppose you want to customize the serialization of only `Passwords` on `User` objects.
|
||||
To do so, you can register the custom `PdxSerializer` for the `User` type by specifying only the fully qualified
|
||||
name of the `Class's` field or property, as the following example shows:
|
||||
|
||||
.Registering custom `PdxSerializers` by POJO field/property name
|
||||
====
|
||||
@@ -230,20 +230,20 @@ customPdxSerializers.put("example.app.auth.model.User.password", new SaltedHashP
|
||||
mappingPdxSerializer.setCustomPdxSerializers(customPdxSerializers);
|
||||
----
|
||||
|
||||
Notice the use of the fully-qualified field/propety name (i.e. "example.app.auth.model.User.password")
|
||||
Notice the use of the fully-qualified field or propety name (that is `example.app.auth.model.User.password`)
|
||||
as the custom `PdxSerializer` registration key.
|
||||
|
||||
NOTE: You could construct the registration key using a more logical code snippet, such as:
|
||||
`User.class.getName().concat(".password");` This is recommended over the example shown above. The example was simply
|
||||
trying to be very explicit in the semantics of registration.
|
||||
NOTE: You could construct the registration key by using a more logical code snippet, such as the following:
|
||||
`User.class.getName().concat(".password");`. We recommended this over the example shown earlier. The preceding example
|
||||
tried to be as explicit as possible about the semantics of registration.
|
||||
|
||||
[[mapping.pdx-serializer.id-properties]]
|
||||
=== Mapping ID Properties
|
||||
|
||||
Like Pivotal GemFire's `ReflectionBasedAutoSerializer`, SDG's `MappingPdxSerializer` is also able to determine
|
||||
the identifier of the entity. However, `MappingPdxSerializer` does so by using Spring Data's mapping meta-data,
|
||||
specifically by finding the entity property designated as the identifier using the
|
||||
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/annotation/Id.html[`@Id`] Spring Data annotation.
|
||||
the identifier of the entity. However, `MappingPdxSerializer` does so by using Spring Data's mapping metadata,
|
||||
specifically by finding the entity property designated as the identifier by using Spring Data's
|
||||
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/annotation/Id.html[`@Id`] annotation.
|
||||
|
||||
For example:
|
||||
|
||||
@@ -258,7 +258,7 @@ class Customer {
|
||||
}
|
||||
----
|
||||
|
||||
In this case, the `Customer's` `id` field will be marked as the identifier field in the PDX type meta-data using
|
||||
In this case, the `Customer` `id` field is marked as the identifier field in the PDX type metadata by using
|
||||
http://gemfire-95-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxWriter.html#markIdentityField-java.lang.String-[`PdxWriter.markIdentifierField(:String)`]
|
||||
when the `PdxSerializer.toData(..)` method is called during serialization.
|
||||
|
||||
@@ -267,8 +267,8 @@ when the `PdxSerializer.toData(..)` method is called during serialization.
|
||||
|
||||
What happens when your entity defines a read-only property?
|
||||
|
||||
First, it is important to understand what a "read-only" property is. If you define a POJO following the http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html[JavaBeans]
|
||||
specification (as Spring does), and you have defined a POJO with some read-only property as follows:
|
||||
First, it is important to understand what a "`read-only`" property is. If you define a POJO by following the http://www.oracle.com/technetwork/java/javase/documentation/spec-136004.html[JavaBeans]
|
||||
specification (as Spring does), you might a POJO with a read-only property, as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -286,33 +286,33 @@ class ApplicationDomainType {
|
||||
}
|
||||
----
|
||||
|
||||
Then the `readOnly` property is "read-only" because it does not provide a setter method; it only has a getter method.
|
||||
Then the `readOnly` property is "`read-only`" because it does not provide a setter method. It has only a getter method.
|
||||
In this case, the `readOnly` property (not to be confused with the `readOnly` `DomainType` field)
|
||||
is considered "read-only".
|
||||
is considered "`read-only`".
|
||||
|
||||
As such, the `MappingPdxSerializer` will not try to write this value back when populating the instance of `DomainType`
|
||||
As a result, the `MappingPdxSerializer` does not try to write this value back when populating the instance of `DomainType`
|
||||
in the `PdxSerializer.fromData(:Class<?>, :PdxReader)` method.
|
||||
|
||||
This is useful in situations where you might be returning a view or projection of some entity type and you only want
|
||||
to write state that is writable. Perhaps the view or projection of the entity is based on authorization or some other
|
||||
criteria. The point is, you can leverage this feature as is appropriate for your application use cases and requirements.
|
||||
If you want the field/property to always be written then simply define a setter.
|
||||
to write state that is writable. Perhaps the view or projection of the entity is based on authorization or some other
|
||||
criteria. The point is that you can leverage this feature as is appropriate for your application's use cases and requirements.
|
||||
If you want the field or property to always be written, you can define a setter.
|
||||
|
||||
[[mapping.pdx-serializer.transient-properties]]
|
||||
=== Mapping Transient Properties
|
||||
|
||||
Likewise, what happens when your entity defines `transient` properties?
|
||||
|
||||
You would expect the `transient` fields/properties of your entity not to be serialized to the stream of PDX bytes
|
||||
when serializing entity. And, that is exactly what happens, unlike Pivotal GemFire's own
|
||||
`ReflectionBasedAutoSerializer`, which serializes everything accessible from the object via _Java Reflection_.
|
||||
You would expect the `transient` fields or properties of your entity not to be serialized to the stream of PDX bytes
|
||||
when serializing entity. That is exactly what happens, unlike Pivotal GemFire's own
|
||||
`ReflectionBasedAutoSerializer`, which serializes everything accessible from the object through Java reflection.
|
||||
|
||||
The `MappingPdxSerializer` will not serialize any fields or properties which are qualified as transient either using
|
||||
Java's `transient` keyword (in the case of fields) or when using the
|
||||
The `MappingPdxSerializer` does not serialize any fields or properties that are qualified as being transient either by using
|
||||
Java's `transient` keyword (in the case of fields) or by using the
|
||||
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/annotation/Transient.html[`@Transient`]
|
||||
Spring Data annotation on either fields or properties.
|
||||
|
||||
For example, if you defined an enity with transient fields and properties, like so...
|
||||
For example, you might define an entity with transient fields and properties as follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -337,29 +337,29 @@ class Process {
|
||||
}
|
||||
----
|
||||
|
||||
Neither the `Process` `id` field nor the readable `hostname` property will be written to the PDX serialized bytes.
|
||||
Neither the `Process` `id` field nor the readable `hostname` property are written to the PDX serialized bytes.
|
||||
|
||||
[[mapping.pdx-serializer.type-filtering]]
|
||||
=== Filtering by Class types
|
||||
|
||||
Similar to Pivotal GemFire's `ReflectionBasedAutoSerializer`, SDG's `MappingPdxSerializer` allows a user to filter
|
||||
the types of objects that the `MappingPdxSerializer` will handle, i.e. de/serialize.
|
||||
Similar to Pivotal GemFire's `ReflectionBasedAutoSerializer`, SDG's `MappingPdxSerializer` lets you filter
|
||||
the types of objects that the `MappingPdxSerializer` serializes and deserializes.
|
||||
|
||||
However, unlike Pivotal GemFire's `ReflectionBasedAutoSerializer`, which uses complex _Regular Expressions_ to express
|
||||
which types the serializer will handle, SDG's `MappingPdxSerializer` uses the much more robust
|
||||
However, unlike Pivotal GemFire's `ReflectionBasedAutoSerializer`, which uses complex regular expressions to express
|
||||
which types the serializer handles, SDG's `MappingPdxSerializer` uses the much more robust
|
||||
https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html[`java.util.function.Predicate`] interface
|
||||
and API to express type matching criteria.
|
||||
and API to express type-matching criteria.
|
||||
|
||||
Plus, if you feel strongly about using _Regular Expressions_, then you can always implement a `Predicate` using
|
||||
_Java's_ https://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html[_Regular Expression_ support].
|
||||
If you like to use regular expressions, you can implement a `Predicate` by using
|
||||
Java's https://docs.oracle.com/javase/8/docs/api/java/util/regex/package-summary.html[regular expression support].
|
||||
|
||||
The nice part about Java's `Predicate` interface is that you can compose `Predicates` using the convenient
|
||||
and appropriate API:
|
||||
The nice part about Java's `Predicate` interface is that you can compose `Predicates` by using convenient
|
||||
and appropriate API methods, including:
|
||||
https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html#and-java.util.function.Predicate-[`and(:Predicate)`],
|
||||
https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html#or-java.util.function.Predicate-[`or(:Predicate)`]
|
||||
https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html#or-java.util.function.Predicate-[`or(:Predicate)`],
|
||||
and https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html#negate--[`negate()`].
|
||||
|
||||
For example:
|
||||
The following example shows the `Predicate` API in use:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -376,6 +376,6 @@ For example:
|
||||
----
|
||||
|
||||
NOTE: In addition to setting your own type filtering `Predicates`, SDG's `MappingPdxSerializer` now automatically
|
||||
registers pre-canned `Predicates` that filters types from the `org.apache.geode` package along with `null` objects
|
||||
registers pre-defined `Predicates` that filter types from the `org.apache.geode` package along with `null` objects
|
||||
when calling `PdxSerializer.toData(:Object, :PdxWriter)` or `null` `Class` types when calling
|
||||
`PdxSerializer.fromData(:Class<?>, :PdxReader)` methods.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,17 +1,15 @@
|
||||
[[gemfire-repositories]]
|
||||
= Spring Data for Pivotal GemFire Repositories
|
||||
|
||||
== Introduction
|
||||
|
||||
_Spring Data for Pivotal GemFire_ provides support to use the _Spring Data Repository_ abstraction to easily persist entities
|
||||
into Pivotal GemFire along with execute queries. A general introduction to the _Repository programming model_ is provided
|
||||
Spring Data for Pivotal GemFire provides support for using the Spring Data Repository abstraction to easily persist entities
|
||||
into Pivotal GemFire along with execute queries. A general introduction to the repository programming model is provided
|
||||
http://docs.spring.io/spring-data/data-commons/docs/current/reference/html/#repositories[here].
|
||||
|
||||
[[gemfire-repositories.spring-configuration-xml]]
|
||||
== Spring XML Configuration
|
||||
|
||||
To bootstrap _Spring Data Repositories_, you use the `<repositories/>` element from the _Spring Data for Pivotal GemFire_
|
||||
Data namespace:
|
||||
To bootstrap Spring Data Repositories, use the `<repositories/>` element from the Spring Data for Pivotal GemFire
|
||||
Data namespace, as the following example shows:
|
||||
|
||||
.Bootstrap Spring Data for Pivotal GemFire Repositories in XML
|
||||
====
|
||||
@@ -30,20 +28,19 @@ Data namespace:
|
||||
----
|
||||
====
|
||||
|
||||
This configuration snippet looks for interfaces below the configured base package and creates _Repository_ instances
|
||||
for those interfaces backed by a `SimplePivotal GemFireRepository`.
|
||||
The preceding configuration snippet looks for interfaces below the configured base package and creates repository instances
|
||||
for those interfaces backed by a https://docs.spring.io/spring-data/geode/docs/current/api/org/springframework/data/gemfire/repository/support/SimpleGemfireRepository.html[`SimpleGemFireRepository`].
|
||||
|
||||
IMPORTANT: You must have your application domain classes correctly mapped to configured Regions
|
||||
or the bootstrap process will fail otherwise.
|
||||
IMPORTANT: The bootstrap process fails unless you have your application domain classes correctly mapped to configured regions.
|
||||
|
||||
[[gemfire-repositories.spring-configuration-java]]
|
||||
== Spring Java-based Configuration
|
||||
|
||||
Alternatively, many users prefer to use _Spring's_
|
||||
Alternatively, many developers prefer to use Spring's
|
||||
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-java[Java-based container configuration].
|
||||
|
||||
Using this approach, it is a simple matter to bootstrap _Spring Data Repositories_ using the SDG `@EnableGemfireRepositories`
|
||||
annotation:
|
||||
Using this approach, you can bootstrap Spring Data Repositories by using the SDG `@EnableGemfireRepositories`
|
||||
annotation, as the following example shows:
|
||||
|
||||
.Bootstrap _Spring Data for Pivotal GemFire Repositories_ with `@EnableGemfireRepositories`
|
||||
====
|
||||
@@ -58,46 +55,46 @@ class SpringDataApplication {
|
||||
====
|
||||
|
||||
Rather than use the `basePackages` attribute, you may prefer to use the type-safe `basePackageClasses` attribute instead.
|
||||
The `basePackageClasses` allows you to specify the package containing all your application _Repository_ classes
|
||||
by specifying just one of your application _Repository_ interface types. Consider creating a special no-op marker class
|
||||
or interface in each package that serves no other purpose than to identify the location of application _Repositories_
|
||||
The `basePackageClasses` lets you specify the package that contains all your application repository classes
|
||||
by specifying only one of your application repository interface types. Consider creating a special no-op marker class
|
||||
or interface in each package that serves no purpose other than to identify the location of application repositories
|
||||
referenced by this attribute.
|
||||
|
||||
In addition to the `basePackage[sClasses]` attributes, like _Spring's_
|
||||
In addition to the `basePackage[sClasses]` attributes, such as Spring's
|
||||
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.html[`@ComponentScan`] annotation,
|
||||
the `@EnableGemfireRepositories` annotation provides _include_ and _exclude_ filters, based on _Spring's_
|
||||
the `@EnableGemfireRepositories` annotation provides include and exclude filters, based on Spring's
|
||||
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ComponentScan.Filter.html[`ComponentScan.Filter`] type.
|
||||
You can use the `filterType` attribute to filter by different aspects, such as whether an application _Repository_ type
|
||||
is annotated with a particular `Annotation` or extends a particular class type, and so on. See the
|
||||
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/FilterType.html[`FilterType` _Javadoc_]
|
||||
You can use the `filterType` attribute to filter by different aspects, such as whether an application repository type
|
||||
is annotated with a particular annotation or extends a particular class type and so on. See the
|
||||
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/FilterType.html[`FilterType` Javadoc]
|
||||
for more details.
|
||||
|
||||
The `@EnableGemfireRepositories` annotation also provides the ability to specify the location of named OQL queries,
|
||||
which reside in a Java `Properties` file, using the `namedQueriesLocation` attribute. The property name must match
|
||||
the name of a _Repository_ query method and the property value is the OQL query you want executed when
|
||||
the _Repository_ query method is called.
|
||||
The `@EnableGemfireRepositories` annotation also lets you specify the location of named OQL queries,
|
||||
which reside in a Java `Properties` file, by using the `namedQueriesLocation` attribute. The property name must match
|
||||
the name of a repository query method and the property value is the OQL query you want executed when
|
||||
the repository query method is called.
|
||||
|
||||
The `repositoryImplementationPostfix` attribute can be set to an alternate value (defaults to "_Impl_") if your
|
||||
application requires 1 or more https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.custom-implementations[custom _Repository_ implementations].
|
||||
This feature is commonly used to extend the _Spring Data Repository_ infrastructure in order to implement a feature
|
||||
not provided out-of-the-box (OOTB) by the data store (e.g. SDG).
|
||||
The `repositoryImplementationPostfix` attribute can be set to an alternate value (defaults to `Impl`) if your
|
||||
application requires one or more https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories.custom-implementations[custom repository implementations].
|
||||
This feature is commonly used to extend the Spring Data repository infrastructure to implement a feature
|
||||
not provided by the data store (for example, SDG).
|
||||
|
||||
One example of where custom _Repository_ implementations are needed with Pivotal GemFire is when performing _Joins_.
|
||||
_Joins_ are not supported by SDG _Repositories_ OOTB. With a Pivotal GemFire `PARTITION` Region, the _Join_ must be
|
||||
performed on collocated `PARTITION` Regions even, since Pivotal GemFire does not support "distributed" _Joins_.
|
||||
In addition, the _Equi-Join_ OQL Query must be performed inside a Pivotal GemFire Function.
|
||||
One example of where custom repository implementations are needed with Pivotal GemFire is when performing joins.
|
||||
Joins are not supported by SDG repositories. With a Pivotal GemFire `PARTITION` Region, the join must be
|
||||
performed on co-located `PARTITION` regions, since Pivotal GemFire does not support "`distributed`" joins.
|
||||
In addition, the Equi-Join OQL Query must be performed inside a Pivotal GemFire function.
|
||||
See http://gemfire91.docs.pivotal.io/geode/developing/partitioned_regions/join_query_partitioned_regions.html[here]
|
||||
for more details on Pivotal GemFire _Equi-Join Queries_.
|
||||
|
||||
Many other aspects of the SDG's _Repository_ infrastructure extension maybe customized as well. See the
|
||||
https://docs.spring.io/spring-data/gemfire/docs/current/api/org/springframework/data/gemfire/repository/config/EnableGemfireRepositories.html[`@EnableGemfireRepositories` _Javadoc_]
|
||||
Many other aspects of the SDG's repository infrastructure extension may be customized as well. See the
|
||||
https://docs.spring.io/spring-data/gemfire/docs/current/api/org/springframework/data/gemfire/repository/config/EnableGemfireRepositories.html[`@EnableGemfireRepositories` Javadoc]
|
||||
for more details on all configuration settings.
|
||||
|
||||
[[gemfire-repositories.queries.executing]]
|
||||
== Executing OQL Queries
|
||||
|
||||
_Spring Data for Pivotal GemFire Repositories_ enable the definition of query methods to easily execute Pivotal GemFire OQL Queries
|
||||
against the Region the managed entity is mapped to.
|
||||
Spring Data for Pivotal GemFire Repositories enable the definition of query methods to easily execute Pivotal GemFire OQL queries
|
||||
against the region the managed entity maps to, as the following example shows:
|
||||
|
||||
.Sample Repository
|
||||
====
|
||||
@@ -124,12 +121,14 @@ public interface PersonRepository extends CrudRepository<Person, Long> {
|
||||
----
|
||||
====
|
||||
|
||||
The first query method listed here will cause the following OQL query to be derived:
|
||||
`SELECT x FROM /People x WHERE x.emailAddress = $1`. The second query method works the same way except
|
||||
it's returning all entities found whereas the first query method expects a single result to be found.
|
||||
The first query method listed in the preceding example causes the following OQL query to be derived:
|
||||
`SELECT x FROM /People x WHERE x.emailAddress = $1`. The second query method works the same way except
|
||||
it returns all entities found, whereas the first query method expects a single result to be found.
|
||||
|
||||
In case the supported keywords are not sufficient to expresss and declare your OQL query, or the method name
|
||||
becomes too verbose, you can annotate the query methods with `@Query` as seen for methods 3 and 4.
|
||||
If the supported keywords are not sufficient to express and declare your OQL query, or the method name
|
||||
becomes too verbose, you can annotate the query methods with `@Query` as shown on the third and fourth methods.
|
||||
|
||||
The following table gives brief samples of the supported keywords that you can use in query methods:
|
||||
|
||||
[cols="1,2,2", options="header"]
|
||||
.Supported keywords for query methods
|
||||
@@ -196,28 +195,28 @@ becomes too verbose, you can annotate the query methods with `@Query` as seen fo
|
||||
|===
|
||||
|
||||
[[gemfire-repositories.queries.oql-extensions]]
|
||||
== OQL Query Extensions using Annotations
|
||||
== OQL Query Extensions Using Annotations
|
||||
|
||||
Many query languages, such as Pivotal GemFire's OQL (Object Query Language), have extensions that are not directly
|
||||
supported by _Spring Data Commons' Repository_ infrastructure.
|
||||
supported by Spring Data Commons' repository infrastructure.
|
||||
|
||||
One of _Spring Data Commons' Repository_ infrastructure goals is to function as the lowest common denominator
|
||||
in order to maintain support for and portability across the widest array of data stores available and in use
|
||||
for application development today. Technically, this means developers can access multiple different data stores
|
||||
supported by _Spring Data Commons_ within their applications by reusing their existing application-specific
|
||||
Repository interfaces, a very convenient and powerful abstraction.
|
||||
One of Spring Data Commons' repository infrastructure goals is to function as the lowest common denominator
|
||||
to maintain support for and portability across the widest array of data stores available and in use
|
||||
for application development today. Technically, this means developers can access multiple different data stores
|
||||
supported by Spring Data Commons within their applications by reusing their existing application-specific
|
||||
repository interfaces -- a convenient and powerful abstraction.
|
||||
|
||||
To support Pivotal GemFire's OQL Query language extensions and preserve portability across different data stores,
|
||||
_Spring Data for Pivotal GemFire_ adds support for OQL Query extensions using Java Annotations. These Annotations will be ignored
|
||||
by other _Spring Data Repository_ implementations (e.g. _Spring Data_ JPA or _Spring Data Redis_) that do not have
|
||||
Spring Data for Pivotal GemFire adds support for OQL Query extensions by using Java annotations. These Annotations are ignored
|
||||
by other Spring Data repository implementations (such as Spring Data JPA or Spring Data Redis) that do not have
|
||||
similar query language extensions.
|
||||
|
||||
For instance, many data stores will most likely not implement Pivotal GemFire's OQL `IMPORT` keyword. By implementing `IMPORT`
|
||||
as an Annotation (i.e. `@Import`) rather than as part of the query method signature (specifically, the method 'name'),
|
||||
then this will not interfere with the parsing infrastructure when evaluating the query method name to construct
|
||||
For instance, many data stores most likely do not implement Pivotal GemFire's OQL `IMPORT` keyword. Implementing `IMPORT`
|
||||
as an annotation (that is, `@Import`) rather than as part of the query method signature (specifically, the method 'name')
|
||||
does not interfere with the parsing infrastructure when evaluating the query method name to construct
|
||||
another data store language appropriate query.
|
||||
|
||||
Currently, the set of Pivotal GemFire OQL Query language extensions that are supported by _Spring Data for Pivotal GemFire_ include:
|
||||
Currently, the set of Pivotal GemFire OQL Query language extensions that are supported by Spring Data for Pivotal GemFire include:
|
||||
|
||||
[cols="1,2,2,2", options="header"]
|
||||
.Supported Pivotal GemFire OQL extensions for Repository query methods
|
||||
@@ -229,7 +228,7 @@ Currently, the set of Pivotal GemFire OQL Query language extensions that are sup
|
||||
|
||||
| http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/query_index_hints.html#topic_cfb_mxn_jq[HINT]
|
||||
| `@Hint`
|
||||
| OQL Query Index Hints
|
||||
| OQL query index hints
|
||||
| `String[]` (e.g. @Hint({ "IdIdx", "TxDateIdx" }))
|
||||
|
||||
| http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_select/the_import_statement.html#concept_2E9F15B2FE9041238B54736103396BF7[IMPORT]
|
||||
@@ -244,12 +243,12 @@ Currently, the set of Pivotal GemFire OQL Query language extensions that are sup
|
||||
|
||||
| http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_additional/query_debugging.html#concept_2D557E24AAB24044A3DB36B3124F6748[TRACE]
|
||||
| `@Trace`
|
||||
| Enable OQL Query specific debugging.
|
||||
| Enable OQL query-specific debugging.
|
||||
| NA
|
||||
|===
|
||||
|
||||
As an example, suppose you have a `Customers` application domain class and corresponding Pivotal GemFire Region along with a
|
||||
`CustomerRepository` and a query method to lookup `Customers` by last name, like so...
|
||||
As an example, suppose you have a `Customers` application domain class and corresponding Pivotal GemFire region along with a
|
||||
`CustomerRepository` and a query method to lookup `Customers` by last name, as follows:
|
||||
|
||||
.Sample Customers Repository
|
||||
====
|
||||
@@ -291,15 +290,14 @@ public interface CustomerRepository extends GemfireRepository<Customer, Long> {
|
||||
----
|
||||
====
|
||||
|
||||
This will result in the following OQL Query:
|
||||
The preceding example results in the following OQL Query:
|
||||
|
||||
`<TRACE> <HINT 'LastNameIdx'> IMPORT org.example.app.domain.Customer; SELECT * FROM /Customers x WHERE x.lastName = $1 LIMIT 10`
|
||||
|
||||
_Spring Data for Pivotal GemFire's Repository_ extension and support is careful not to create conflicting declarations when
|
||||
Spring Data for Pivotal GemFire's repository extension and support is careful not to create conflicting declarations when
|
||||
the OQL Annotation extensions are used in combination with the `@Query` annotation.
|
||||
|
||||
As another example, suppose you have a raw `@Query` annotated query method defined in your `CustomerRepository`
|
||||
like so...
|
||||
As another example, suppose you have a raw `@Query` annotated query method defined in your `CustomerRepository`, as follows:
|
||||
|
||||
.CustomerRepository
|
||||
====
|
||||
@@ -317,33 +315,33 @@ public interface CustomerRepository extends GemfireRepository<Customer, Long> {
|
||||
----
|
||||
====
|
||||
|
||||
This query method results in the following OQL Query:
|
||||
The preceding query method results in the following OQL Query:
|
||||
|
||||
`IMPORT org.example.app.domain.Customer; <TRACE> <HINT 'ReputationIdx'> SELECT DISTINCT * FROM /Customers x
|
||||
WHERE x.reputation > $1 ORDER BY c.reputation DESC LIMIT 5`
|
||||
|
||||
As you can see, the `@Limit(10)` annotation will +not+ override the `LIMIT` defined explicitly in the raw query.
|
||||
As well, `@Hint("CustomerIdx")` annotation does +not+ override the `HINT` explicitly defined in the raw query.
|
||||
The `@Limit(10)` annotation does not override the `LIMIT` defined explicitly in the raw query.
|
||||
Also, the `@Hint("CustomerIdx")` annotation does not override the `HINT` explicitly defined in the raw query.
|
||||
Finally, the `@Trace` annotation is redundant and has no additional effect.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The "ReputationIdx" Index is probably not the most sensible index given the number of Customers who will possibly have
|
||||
the same value for their reputation, which will effectively reduce the effectiveness of the index. Please choose
|
||||
indexes and other optimizations wisely as an improper or poorly choosen index can have the opposite effect on your
|
||||
performance given the overhead in maintaining the index. The "ReputationIdx" was only used to serve the purpose
|
||||
The `ReputationIdx` index is probably not the most sensible index, given the number of customers who may possibly have
|
||||
the same value for their reputation, which reduces the effectiveness of the index. Please choose
|
||||
indexes and other optimizations wisely, as an improper or poorly chosen index can have the opposite effect on your
|
||||
performance because of the overhead in maintaining the index. The `ReputationIdx` was used only to serve the purpose
|
||||
of the example.
|
||||
====
|
||||
|
||||
[[gemfire-repositories.queries.post-processing]]
|
||||
== Query Post Processing
|
||||
|
||||
Using the Spring Data _Repository_ abstraction, query method convention for defining data store specific queries
|
||||
(e.g. OQL) is easy and convenient. However, it is sometimes desirable to still want to inspect or even possibly
|
||||
modify the query "generated" from the _Repository_ query method.
|
||||
Thanks to using the Spring Data repository abstraction, the query method convention for defining data store specific queries
|
||||
(e.g. OQL) is easy and convenient. However, it is sometimes desirable to still want to inspect or even possibly
|
||||
modify the query generated from the repository query method.
|
||||
|
||||
Since 2.0.x, _Spring Data for Pivotal GemFire_ introduces the `o.s.d.gemfire.repository.query.QueryPostProcessor`
|
||||
functional interface. The interface is loosely defined as follows...
|
||||
Since 2.0.x, Spring Data for Pivotal GemFire includes the `o.s.d.gemfire.repository.query.QueryPostProcessor`
|
||||
functional interface. The interface is loosely defined as follows:
|
||||
|
||||
.QueryPostProcessor
|
||||
====
|
||||
@@ -365,31 +363,31 @@ interface QueryPostProcessor<T extends Repository, QUERY> extends Ordered {
|
||||
----
|
||||
====
|
||||
|
||||
There are additional default methods provided to allow users to compose instances of `QueryPostProcessor` very similar
|
||||
There are additional default methods provided that let you compose instances of `QueryPostProcessor` similar
|
||||
to how https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html#compose-java.util.function.Function-[java.util.function.Function.andThen(:Function)]
|
||||
and https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html#compose-java.util.function.Function-[java.util.function.Function.compose(:Function)]
|
||||
work.
|
||||
|
||||
Additionally, you will notice that the `QueryPostProcessor` interface implements the
|
||||
Additionally, the `QueryPostProcessor` interface implements the
|
||||
https://docs.spring.io/spring/docs/5.0.2.RELEASE/javadoc-api/org/springframework/core/Ordered.html[`org.springframework.core.Ordered`]
|
||||
interface, which is useful when multiple `QueryPostProcessors` are declared and registered in the Spring context
|
||||
and used to create a pipeline of processing for a group of generated query method queries.
|
||||
|
||||
Finally, the `QueryPostProcessor` accepts type arguments corresponding to the type parameters, `T` and `QUERY`,
|
||||
respectively. Type of `T` extends the _Spring Data Commons_ marker interface,
|
||||
respectively. Type of `T` extends the Spring Data Commons marker interface,
|
||||
https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/repository/Repository.html[`org.springframework.data.repository.Repository`].
|
||||
We will discuss this further below. All `QUERY` type parameter arguments in _Spring Data for Pivotal GemFire's_ case
|
||||
will be of type `java.lang.String`.
|
||||
We discuss this further later in this section. All `QUERY` type parameter arguments in Spring Data for Pivotal GemFire's case
|
||||
are of type `java.lang.String`.
|
||||
|
||||
NOTE: It is useful to define the query as type `QUERY` since this `QueryPostProcessor` interface maybe ported to
|
||||
_Spring Data Commons_ and therefore must handle all forms of queries by different data stores (e.g. JPA, MongoDB,
|
||||
NOTE: It is useful to define the query as type `QUERY`, since this `QueryPostProcessor` interface may be ported to
|
||||
Spring Data Commons and therefore must handle all forms of queries by different data stores (such as JPA, MongoDB,
|
||||
or Redis).
|
||||
|
||||
As user may implement this interface to receive a callback with the query that was generated from the application
|
||||
You can implement this interface to receive a callback with the query that was generated from the application
|
||||
`Repository` interface method when the method is called.
|
||||
|
||||
For example, I might want to log all queries from all application _Repository_ interface definitions. I could do so
|
||||
using the following `QueryPostProcessor` implementation...
|
||||
For example, you might want to log all queries from all application repository interface definitions. You could do so by
|
||||
using the following `QueryPostProcessor` implementation:
|
||||
|
||||
.LoggingQueryPostProcessor
|
||||
====
|
||||
@@ -415,10 +413,10 @@ class LoggingQueryPostProcessor implements QueryPostProcessor<Repository, String
|
||||
====
|
||||
|
||||
The `LoggingQueryPostProcessor` was typed to the Spring Data `org.springframework.data.repository.Repository`
|
||||
marker interface, and therefore, will log all application _Repository_ interface query method "generated" queries.
|
||||
marker interface, and, therefore, logs all application repository interface query method generated queries.
|
||||
|
||||
You could limit the scope of this logging to queries only from certain types of application _Repository_ interfaces,
|
||||
such as, say, an `CustomerRepository`...
|
||||
You could limit the scope of this logging to queries only from certain types of application repository interfaces,
|
||||
such as, say, a `CustomerRepository`, as the following example shows:
|
||||
|
||||
.CustomerRepository
|
||||
====
|
||||
@@ -434,7 +432,7 @@ interface CustomerRepository extends CrudRepository<Customer, Long> {
|
||||
----
|
||||
====
|
||||
|
||||
Then, I could have typed the `LoggingQueryPostProcessor` specifically to the `CustomerRepository`, like so...
|
||||
Then you could have typed the `LoggingQueryPostProcessor` specifically to the `CustomerRepository`, as follows:
|
||||
|
||||
.CustomerLoggingQueryPostProcessor
|
||||
====
|
||||
@@ -444,12 +442,12 @@ class LoggingQueryPostProcessor implements QueryPostProcessor<CustomerRepository
|
||||
----
|
||||
====
|
||||
|
||||
As result, only queries defined in the `CustomerRepository` interface (e.g. `findByAccountNumber`) would be logged.
|
||||
As a result, only queries defined in the `CustomerRepository` interface (such as `findByAccountNumber`) are logged.
|
||||
|
||||
I might want to create a `QueryPostProcessor` for a specific query defined by a _Repository_ query method. For example,
|
||||
say I want to "`LIMIT`" the OQL query generated from the `CustomerRepository.findByLastNameLike(:String)` query method
|
||||
to only return 5 results and I want to order the `Customers` by `firstName`, ascending. Well, then, I can define
|
||||
a custom `QueryPostProcessor` like so...
|
||||
You might want to create a `QueryPostProcessor` for a specific query defined by a repository query method. For example,
|
||||
suppose you want to limit the OQL query generated from the `CustomerRepository.findByLastNameLike(:String)` query method
|
||||
to only return five results and want to order the `Customers` by `firstName`, ascending. To do so, you can define
|
||||
a custom `QueryPostProcessor`, as the following example shows:
|
||||
|
||||
.OrderedLimitedCustomerByLastNameQueryPostProcessor
|
||||
====
|
||||
@@ -477,8 +475,8 @@ class OrderedLimitedCustomerByLastNameQueryPostProcessor implements QueryPostPro
|
||||
----
|
||||
====
|
||||
|
||||
While this works, it possible to achieve the same affect just using the Spring Data _Repository_ convention and extensions
|
||||
provided by _Spring Data for Pivotal GemFire_. For instance, the same query could be defined as...
|
||||
While the preceding example works, you can achieve the same effect by using the Spring Data repository convention and extensions
|
||||
provided by Spring Data for Pivotal GemFire. For instance, the same query could be defined as follows:
|
||||
|
||||
.CustomerRepository using the convention
|
||||
====
|
||||
@@ -494,11 +492,11 @@ interface CustomerRepository extends CrudRepository<Customer, Long> {
|
||||
====
|
||||
|
||||
However, if you do not have control over the application `CustomerRepository` interface definition,
|
||||
then the `QueryPostProcessor` (i.e. `OrderedLimitedCustomerByLastNameQueryPostProcessor`) is convenient.
|
||||
then the `QueryPostProcessor` (that is, `OrderedLimitedCustomerByLastNameQueryPostProcessor`) is convenient.
|
||||
|
||||
If I want to ensure the `LoggingQueryPostProcessor` always comes after the other application-defined `QueryPostProcessors`
|
||||
that I may have declared and registered in the Spring `ApplicationContext`, then I can set the `order` property
|
||||
by overriding the `o.s.core.Ordered.getOrder()` method.
|
||||
If you want to ensure that the `LoggingQueryPostProcessor` always comes after the other application-defined `QueryPostProcessors`
|
||||
that may have declared and registered in the Spring `ApplicationContext`, you can set the `order` property
|
||||
by overriding the `o.s.core.Ordered.getOrder()` method, as the following example shows:
|
||||
|
||||
.Defining the `order` property
|
||||
====
|
||||
@@ -522,9 +520,9 @@ class CustomerQueryPostProcessor implements QueryPostProcessor<CustomerRepositor
|
||||
----
|
||||
====
|
||||
|
||||
This ensures that I will always see the affects of the post processing applied by my other `QueryPostProcessors`
|
||||
before my `LoggingQueryPostProcessor` logs the query.
|
||||
This ensures that you always see the effects of the post processing applied by other `QueryPostProcessors`
|
||||
before the `LoggingQueryPostProcessor` logs the query.
|
||||
|
||||
You can define as many `QueryPostProcessors` in the Spring `ApplicationContext` as you like and apply them in any
|
||||
order, to all or specific application _Repository_ interfaces, and be a granular as yuo like using the provided
|
||||
order, to all or specific application repository interfaces, and be as granular as you like by using the provided
|
||||
arguments to the `postProcess(..)` method callback.
|
||||
|
||||
@@ -4,43 +4,42 @@
|
||||
NOTE: Sample applications are now maintained in the
|
||||
https://github.com/spring-projects/spring-gemfire-examples[Spring Pivotal GemFire Examples] repository.
|
||||
|
||||
The _Spring Data for Pivotal GemFire_ project also includes one sample application. Named "Hello World", the sample application
|
||||
demonstrates how to configure and use Pivotal GemFire inside a _Spring_ application. At runtime, the sample offers
|
||||
a *shell* to the user allowing her to run various commands against the data grid. It provides an excellent
|
||||
starting point for users unfamiliar with the essential components or with _Spring_ and Pivotal GemFire concepts.
|
||||
The Spring Data for Pivotal GemFire project also includes one sample application. Named "`Hello World`", the sample application
|
||||
demonstrates how to configure and use Pivotal GemFire inside a Spring application. At run time, the sample offers
|
||||
a shell that lets you run various commands against the data grid. It provides an excellent
|
||||
starting point for developers who are unfamiliar with the essential components or with Spring and Pivotal GemFire concepts.
|
||||
|
||||
The sample is bundled with the distribution and is Maven-based. A developer can easily import them into any
|
||||
Maven-aware IDE (such as https://spring.io/tools/sts[Spring Tool Suite]) or run them from the command-line.
|
||||
The sample is bundled with the distribution and is Maven-based. You can import it into any
|
||||
Maven-aware IDE (such as the https://spring.io/tools/sts[Spring Tool Suite]) or run them from the command-line.
|
||||
|
||||
[[samples:hello-world]]
|
||||
== Hello World
|
||||
|
||||
The Hello World sample application demonstrates the core functionality of the _Spring Data for Pivotal GemFire_ project.
|
||||
It bootstraps Pivotal GemFire, configures it, executes arbitrary commands against the cache and shuts it down
|
||||
when the application exits. Multiple instances of the application can be started at the same time
|
||||
and they will work together, sharing data without any user intervention.
|
||||
The "`Hello World`" sample application demonstrates the core functionality of the Spring Data for Pivotal GemFire project.
|
||||
It bootstraps Pivotal GemFire, configures it, executes arbitrary commands against the cache, and shuts it down
|
||||
when the application exits. Multiple instances of the application can be started at the same time
|
||||
and work together, sharing data without any user intervention.
|
||||
|
||||
.Running under Linux
|
||||
NOTE: If you experience networking problems when starting Pivotal GemFire or the samples, try adding the following
|
||||
system property `java.net.preferIPv4Stack=true` to the command line (e.g. `-Djava.net.preferIPv4Stack=true`).
|
||||
For an alternative (global) fix especially on Ubuntu see https://jira.spring.io/browse/SGF-28[SGF-28].
|
||||
system property `java.net.preferIPv4Stack=true` to the command line (for example, `-Djava.net.preferIPv4Stack=true`).
|
||||
For an alternative (global) fix (especially on Ubuntu), see https://jira.spring.io/browse/SGF-28[SGF-28].
|
||||
|
||||
[[samples:hello-world:start-stop]]
|
||||
=== Starting and stopping the sample
|
||||
=== Starting and Stopping the Sample
|
||||
|
||||
Hello World is designed as a stand-alone Java application. It features a `main` class which can be started
|
||||
either from your IDE of choice (in Eclipse/STS through `Run As/Java Application`) or from the command-line
|
||||
through Maven using `mvn exec:java`. A developer can also use `java` directly on the resulting artifact
|
||||
if the classpath is properly set.
|
||||
The "`Hello World`" sample application is designed as a stand-alone Java application. It features a `main` class that can be started
|
||||
either from your IDE (in Eclipse or STS, through `Run As/Java Application`) or from the command line
|
||||
through Maven with `mvn exec:java`. If the classpath is properly set, you can also use `java` directly on the resulting artifact.
|
||||
|
||||
To stop the sample, simply type `exit` at the command-line or press `Ctrl+C` to stop the JVM and shutdown
|
||||
the _Spring_ container.
|
||||
To stop the sample, type `exit` at the command line or press `Ctrl+C` to stop the JVM and shutdown
|
||||
the Spring container.
|
||||
|
||||
[[samples:hello-world:run]]
|
||||
=== Using the sample
|
||||
=== Using the Sample
|
||||
|
||||
Once started, the sample will create a shared data grid and allow the user to issue commands against it.
|
||||
The output will likely look as follows:
|
||||
Once started, the sample creates a shared data grid and lets you issue commands against it.
|
||||
The output should resemble the following:
|
||||
|
||||
[source]
|
||||
----
|
||||
@@ -57,7 +56,7 @@ remove <key> - removes an entry (by key) from the grid
|
||||
...
|
||||
----
|
||||
|
||||
For example to add new items to the grid one can use:
|
||||
For example, to add new items to the grid, you can use the following commands:
|
||||
|
||||
[source]
|
||||
----
|
||||
@@ -76,8 +75,8 @@ null
|
||||
2
|
||||
----
|
||||
|
||||
Multiple instances can be ran at the same time. Once started, the new VMs automatically see the existing Region
|
||||
and its information:
|
||||
Multiple instances can be ran at the same time. Once started, the new VMs automatically see the existing region
|
||||
and its information, as the following example shows:
|
||||
|
||||
[source]
|
||||
----
|
||||
@@ -93,22 +92,22 @@ Hello World!
|
||||
[one, two]
|
||||
----
|
||||
|
||||
Experiment with the example, start (and stop) as many instances as you want, run various commands in one instance
|
||||
and see how the others react. To preserve data, at least one instance needs to be alive all times. If all instances
|
||||
We encourage you to experiment with the example, start (and stop) as many instances as you want, and run various commands in one instance
|
||||
and see how the others react. To preserve data, at least one instance needs to be alive all times. If all instances
|
||||
are shutdown, the grid data is completely destroyed.
|
||||
|
||||
[[samples:hello-world:explained]]
|
||||
=== Hello World Sample Explained
|
||||
|
||||
Hello World uses both _Spring_ XML and annotations for its configuration. The initial bootstrapping configuration is
|
||||
The "`Hello World`" sample uses both Spring XML and annotations for its configuration. The initial bootstrapping configuration is
|
||||
`app-context.xml`, which includes the cache configuration defined in the `cache-context.xml` file
|
||||
and performs classpath
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-classpath-scanning[component scanning]
|
||||
for _Spring_
|
||||
for Spring
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-annotation-config[components].
|
||||
|
||||
The cache configuration defines the Pivotal GemFire cache, Region and for illustrative purposes, a simple `CacheListener`
|
||||
The cache configuration defines the Pivotal GemFire cache, a region, and for illustrative purposes, a `CacheListener`
|
||||
that acts as a logger.
|
||||
|
||||
The main *beans* are `HelloWorld` and `CommandProcessor` which rely on the `GemfireTemplate` to interact with
|
||||
the distributed fabric. Both classes use annotations to define their dependency and life-cycle callbacks.
|
||||
The main beans are `HelloWorld` and `CommandProcessor`, which rely on the `GemfireTemplate` to interact with
|
||||
the distributed fabric. Both classes use annotations to define their dependency and life-cycle callbacks.
|
||||
|
||||
@@ -3,37 +3,37 @@
|
||||
|
||||
To improve overall performance of the Pivotal GemFire In-memory Data Grid, Pivotal GemFire supports a dedicated
|
||||
serialization protocol, called PDX, that is both faster and offers more compact results over
|
||||
standard Java serialization in addition to works transparently across various language platforms (Java, C++, .NET).
|
||||
Please refer to
|
||||
standard Java serialization in addition to working transparently across various language platforms (Java, C++, and .NET).
|
||||
See
|
||||
http://geode.apache.org/docs/guide/11/developing/data_serialization/PDX_Serialization_Features.html[PDX Serialization Features]
|
||||
and
|
||||
https://cwiki.apache.org/confluence/display/GEODE/PDX+Serialization+Internals[PDX Serialization Internals]
|
||||
for more details.
|
||||
|
||||
This chapter discusses the various ways in which _Spring Data for Pivotal GemFire_ simplifies and improves Pivotal GemFire's
|
||||
This chapter discusses the various ways in which Spring Data for Pivotal GemFire simplifies and improves Pivotal GemFire's
|
||||
custom serialization in Java.
|
||||
|
||||
[[serialization:wiring]]
|
||||
== Wiring deserialized instances
|
||||
|
||||
It is fairly common for serialized objects to have transient data. Transient data is often dependent on the system
|
||||
or environment where it lives at a certain point in time. For instance, a `DataSource` is environment specific.
|
||||
Serializing such information is useless, and potentially even dangerous, since it is local to a certain VM/machine.
|
||||
For such cases, _Spring Data for Pivotal GemFire_ offers a special
|
||||
or environment where it lives at a certain point in time. For instance, a `DataSource` is environment specific.
|
||||
Serializing such information is useless and potentially even dangerous, since it is local to a certain VM or machine.
|
||||
For such cases, Spring Data for Pivotal GemFire offers a special
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/Instantiator.html[`Instantiator`]
|
||||
that performs wiring for each new instance created by Pivotal GemFire during deserialization.
|
||||
|
||||
Through such a mechanism, one can rely on the _Spring_ container to inject and manage certain dependencies
|
||||
making it easy to split transient from persistent data and have *rich domain objects* in a transparent manner.
|
||||
Through such a mechanism, you can rely on the Spring container to inject and manage certain dependencies,
|
||||
making it easy to split transient from persistent data and have rich domain objects in a transparent manner.
|
||||
|
||||
_Spring_ users might find this approach similar to that of
|
||||
Spring users might find this approach similar to that of
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#aop-atconfigurable[`@Configurable`]).
|
||||
The `WiringInstantiator` works just like `WiringDeclarableSupport`, trying to first locate a bean definition
|
||||
as a wiring template and falling back to autowiring otherwise.
|
||||
The `WiringInstantiator` works similarly to `WiringDeclarableSupport`, trying to first locate a bean definition
|
||||
as a wiring template and otherwise falling back to autowiring.
|
||||
|
||||
Please refer to the previous section (<<apis:declarable>>) for more details on wiring functionality.
|
||||
See the previous section (<<apis:declarable>>) for more details on wiring functionality.
|
||||
|
||||
To use this SDG `Instantiator`, simply declare it as a bean:
|
||||
To use this SDG `Instantiator`, declare it as a bean, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -45,18 +45,18 @@ To use this SDG `Instantiator`, simply declare it as a bean:
|
||||
</bean>
|
||||
----
|
||||
|
||||
During the _Spring_ container startup, once it is being initialized, the `Instantiator` will, by default, register
|
||||
itself with the Pivotal GemFire serialization system and perform wiring on all instances of `SomeDataSerializableClass`
|
||||
During the Spring container startup, once it is being initialized, the `Instantiator`, by default, registers
|
||||
itself with the Pivotal GemFire serialization system and performs wiring on all instances of `SomeDataSerializableClass`
|
||||
created by Pivotal GemFire during deserialization.
|
||||
|
||||
[[serialization:instance-generator]]
|
||||
== Auto-generating custom `Instantiators`
|
||||
== Auto-generating Custom `Instantiators`
|
||||
|
||||
For data intensive applications, a large number of instances might be created on each machine as data flows in.
|
||||
Out-of-the-box, Pivotal GemFire uses reflection to create new types, but for some scenarios, this might prove to be expensive.
|
||||
As always, it is good to perform profiling to quantify whether this is the case or not. For such cases,
|
||||
_Spring Data for Pivotal GemFire_ allows the automatic generation of `Instatiator` classes which instantiate a new type
|
||||
(using the default constructor) without the use of reflection:
|
||||
Pivotal GemFire uses reflection to create new types, but, for some scenarios, this might prove to be expensive.
|
||||
As always, it is good to perform profiling to quantify whether this is the case or not. For such cases,
|
||||
Spring Data for Pivotal GemFire allows the automatic generation of `Instatiator` classes, which instantiate a new type
|
||||
(using the default constructor) without the use of reflection. The following example shows how to create an instantiator:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -70,6 +70,6 @@ _Spring Data for Pivotal GemFire_ allows the automatic generation of `Instatiato
|
||||
</bean>
|
||||
----
|
||||
|
||||
The definition above, automatically generates two `Instantiators` for two classes, namely `CustomTypeA`
|
||||
and `CustomTypeB` and registers them with Pivotal GemFire, under user id `1025` and `1026`. The two `Instantiators` avoid
|
||||
The preceding definition automatically generates two `Instantiators` for two classes (`CustomTypeA`
|
||||
and `CustomTypeB`) and registers them with Pivotal GemFire under user ID `1025` and `1026`. The two `Instantiators` avoid
|
||||
the use of reflection and create the instances directly through Java code.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
[[bootstrap:snapshot]]
|
||||
= Configuring the Snapshot Service
|
||||
|
||||
_Spring Data for Pivotal GemFire_ supports `Cache` and `Region` snapshots using
|
||||
Spring Data for Pivotal GemFire supports `cache` and `region` snapshots by using
|
||||
http://geode.apache.org/docs/guide/11/managing/cache_snapshots/chapter_overview.html[Pivotal GemFire's Snapshot Service].
|
||||
The out-of-the-box Snapshot Service support offers several convenient features to simplify the use of Pivotal GemFire's
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/CacheSnapshotService.html[Cache]
|
||||
@@ -9,17 +9,17 @@ and http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snaps
|
||||
Snapshot Service APIs.
|
||||
|
||||
As the http://geode.apache.org/docs/guide/11/managing/cache_snapshots/chapter_overview.html[Pivotal GemFire documentation]
|
||||
describes, snapshots allow you to save and subsequently reload the cached data later, which can be useful for
|
||||
describes, snapshots let you save and subsequently reload the cached data later, which can be useful for
|
||||
moving data between environments, such as from production to a staging or test environment in order to reproduce
|
||||
data-related issues in a controlled context. You can imagine combining _Spring Data for Pivotal GemFire's_ Snapshot Service support
|
||||
data-related issues in a controlled context. You can combine Spring Data for Pivotal GemFire's Snapshot Service support
|
||||
with http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-definition-profiles[Spring's bean definition profiles]
|
||||
to load snapshot data specific to the environment as necessary.
|
||||
|
||||
_Spring Data for Pivotal GemFire's_ support for Pivotal GemFire's Snapshot Service begins with the `<gfe-data:snapshot-service>` element
|
||||
Spring Data for Pivotal GemFire's support for Pivotal GemFire's Snapshot Service begins with the `<gfe-data:snapshot-service>` element
|
||||
from the `<gfe-data>` namespace.
|
||||
|
||||
For example, I might want to define Cache-wide snapshots to be loaded as well as saved using a couple snapshot imports
|
||||
and a data export definition as follows:
|
||||
For example, you can define cache-wide snapshots to be loaded as well as saved by using a couple of snapshot imports
|
||||
and a data export definition, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -31,13 +31,13 @@ and a data export definition as follows:
|
||||
</gfe-data:snapshot-service>
|
||||
----
|
||||
|
||||
You can define as many imports and/or exports as you like. You can define just imports or just exports.
|
||||
The file locations and directory paths can be absolute, or relative to the _Spring Data for Pivotal GemFire_ application,
|
||||
You can define as many imports and exports as you like. You can define only imports or only exports.
|
||||
The file locations and directory paths can be absolute or relative to the Spring Data for Pivotal GemFire application, which is the
|
||||
JVM process's working directory.
|
||||
|
||||
This is a pretty simple example and the Snapshot Service defined in this case refers to the Pivotal GemFire `Cache` with
|
||||
the default name of `gemfireCache` (as described in <<bootstrap:cache>>). If you name your cache bean definition
|
||||
something other than the default, than you can use the `cache-ref` attribute to refer to the cache bean by name:
|
||||
The preceding example is pretty simple, and the Snapshot Service defined in this case refers to the Pivotal GemFire `cache` with
|
||||
the default name of `gemfireCache` (as described in <<bootstrap:cache>>). If you name your cache bean definition
|
||||
something other than the default, you can use the `cache-ref` attribute to refer to the cache bean by name, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -48,8 +48,8 @@ something other than the default, than you can use the `cache-ref` attribute to
|
||||
</gfe-data:snapshot-service>
|
||||
----
|
||||
|
||||
It is also straightforward to define a Snapshot Service for a particular Pivotal GemFire Region by specifying
|
||||
the `region-ref` attribute:
|
||||
You can also define a Snapshot Service for a particular Pivotal GemFire Region by specifying
|
||||
the `region-ref` attribute, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -61,39 +61,39 @@ the `region-ref` attribute:
|
||||
</gfe-data:snapshot-service>
|
||||
----
|
||||
|
||||
When the `region-ref` attribute is specified, _Spring Data for Pivotal GemFire's_ `SnapshotServiceFactoryBean` resolves
|
||||
the `region-ref` attribute value to a Region bean defined in the _Spring_ context and proceeds to create a
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/RegionSnapshotService.html[RegionSnapshotService].
|
||||
The snapshot import and export definitions function the same way, however, the `location` must refer to a file
|
||||
When the `region-ref` attribute is specified, Spring Data for Pivotal GemFire's `SnapshotServiceFactoryBean` resolves
|
||||
the `region-ref` attribute value to a region bean defined in the Spring context and creates a
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/RegionSnapshotService.html[`RegionSnapshotService`].
|
||||
The snapshot import and export definitions function the same way. However, the `location` must refer to a file
|
||||
on export.
|
||||
|
||||
NOTE: Pivotal GemFire is strict about imported snapshot files actually existing before they are referenced. For exports,
|
||||
Pivotal GemFire will create the snapshot file if it does not already exist. If the snapshot file for export already exists,
|
||||
the data will be overwritten.
|
||||
NOTE: Pivotal GemFire is strict about imported snapshot files actually existing before they are referenced. For exports,
|
||||
Pivotal GemFire creates the snapshot file. If the snapshot file for export already exists,
|
||||
the data is overwritten.
|
||||
|
||||
TIP: _Spring Data for Pivotal GemFire_ includes a `suppress-import-on-init` attribute on the `<gfe-data:snapshot-service>` element
|
||||
to suppress the configured Snapshot Service from trying to import data into the Cache or Region on initialization.
|
||||
This is useful when data exported from 1 Region is used to feed the import of another Region, for example.
|
||||
TIP: Spring Data for Pivotal GemFire includes a `suppress-import-on-init` attribute on the `<gfe-data:snapshot-service>` element
|
||||
to suppress the configured Snapshot Service from trying to import data into the cache or region on initialization.
|
||||
Doing so is useful, for example, when data exported from one region is used to feed the import of another region.
|
||||
|
||||
[[bootstrap:snapshot:location]]
|
||||
== Snapshot Location
|
||||
|
||||
For a `Cache`-based Snapshot Service
|
||||
(i.e. http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/CacheSnapshotService.html[CacheSnapshotService])
|
||||
a developer would typically pass it a directory containing all the snapshot files to load rather than
|
||||
(that is, a http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/CacheSnapshotService.html[`CacheSnapshotService`])
|
||||
you would typically pass it a directory containing all the snapshot files to load rather than
|
||||
individual snapshot files, as the overloaded
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/CacheSnapshotService.html#load-java.io.File-org.apache.geode.cache.snapshot.SnapshotOptions.SnapshotFormat-[load]
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/CacheSnapshotService.html#load-java.io.File-org.apache.geode.cache.snapshot.SnapshotOptions.SnapshotFormat[`load`]
|
||||
method in the `CacheSnapshotService` API indicates.
|
||||
|
||||
NOTE: Of course, a developer may use the other, overloaded `load(:File[], :SnapshotFormat, :SnapshotOptions)` method
|
||||
variant to get specific about which snapshot files are to be loaded into the Pivotal GemFire `Cache`.
|
||||
NOTE: Of course, you can use the other, overloaded `load(:File[], :SnapshotFormat, :SnapshotOptions)` method
|
||||
variant to get specific about which snapshot files to load into the Pivotal GemFire `cache`.
|
||||
|
||||
However, _Spring Data for Pivotal GemFire_ recognizes that a typical developer workflow might be to extract and export data
|
||||
from one environment into several snapshot files, zip all of them up, and then conveniently move the ZIP file
|
||||
However, Spring Data for Pivotal GemFire recognizes that a typical developer workflow might be to extract and export data
|
||||
from one environment into several snapshot files, zip all of them up, and then conveniently move the zip file
|
||||
to another environment for import.
|
||||
|
||||
Therefore, _Spring Data for Pivotal GemFire_ enables the developer to specify a JAR or ZIP file on import for a `Cache`-based
|
||||
Snapshot Service as follows:
|
||||
Therefore, Spring Data for Pivotal GemFire lets you specify a jar or zip file on import for a `cache`-based
|
||||
Snapshot Service, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -102,19 +102,19 @@ Snapshot Service as follows:
|
||||
</gfe-data:snapshot-service>
|
||||
----
|
||||
|
||||
_Spring Data for Pivotal GemFire_ will conveniently extract the provided ZIP file and treat it like a directory import (load).
|
||||
Spring Data for Pivotal GemFire conveniently extracts the provided zip file and treats it as a directory import (load).
|
||||
|
||||
[[bootstrap:snapshot:filters]]
|
||||
== Snapshot Filters
|
||||
|
||||
The real power of defining multiple snapshot imports and exports is realized through the use of snapshot filters.
|
||||
Snapshot filters implement Pivotal GemFire's
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/SnapshotFilter.html[SnapshotFilter]
|
||||
interface and are used to filter Region entries for inclusion into the Region on import
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/SnapshotFilter.html[`SnapshotFilter`]
|
||||
interface and are used to filter region entries for inclusion into the region on import
|
||||
and for inclusion into the snapshot on export.
|
||||
|
||||
_Spring Data for Pivotal GemFire_ makes it brain dead simple to utilize snapshot filters on import and export using the `filter-ref`
|
||||
attribute or an anonymous, nested bean definition:
|
||||
Spring Data for Pivotal GemFire lets you use snapshot filters on import and export by using the `filter-ref`
|
||||
attribute or an anonymous, nested bean definition, as the following example shows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -140,22 +140,20 @@ attribute or an anonymous, nested bean definition:
|
||||
</gfe-data:snapshot-service>
|
||||
----
|
||||
|
||||
In addition, more complex snapshot filters can be expressed with the `ComposableSnapshotFilter` _Spring Data for Pivotal GemFire_
|
||||
provided class. This class implements Pivotal GemFire's
|
||||
In addition, you can express more complex snapshot filters by using the `ComposableSnapshotFilter` class.
|
||||
This class implements Pivotal GemFire's
|
||||
http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/snapshot/SnapshotFilter.html[SnapshotFilter]
|
||||
interface as well as the https://en.wikipedia.org/wiki/Composite_pattern[Composite] software design pattern.
|
||||
|
||||
In a nutshell, the https://en.wikipedia.org/wiki/Composite_pattern[Composite] software design pattern allows developers
|
||||
to compose multiple objects of the same type and treat the aggregate as single instance of the object type,
|
||||
a very powerful and useful abstraction.
|
||||
In a nutshell, the https://en.wikipedia.org/wiki/Composite_pattern[Composite] software design pattern lets you
|
||||
compose multiple objects of the same type and treat the aggregate as single instance of the object type -- a
|
||||
powerful and useful abstraction.
|
||||
|
||||
`ComposableSnapshotFilter` has two factory methods, `'and'` and `'or'`, allowing developers to logically combine
|
||||
individual snapshot filters using the AND and OR logical operators, respectively. The factory methods take a
|
||||
`ComposableSnapshotFilter` has two factory methods, `and` and `or`. They let you logically combine
|
||||
individual snapshot filters using the AND and OR logical operators, respectively. The factory methods take a
|
||||
list of `SnapshotFilters`.
|
||||
|
||||
In this case, the developer is only limited by his/her imagination to leverage this powerful construct.
|
||||
|
||||
For instance:
|
||||
The following example shows a definition for a `ComposableSnapshotFilter`:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -171,7 +169,7 @@ For instance:
|
||||
</bean>
|
||||
----
|
||||
|
||||
The developer could then go onto combine the `activesUsersSinceFilter` with another filter using `'or'` like so:
|
||||
You could then go on to combine the `activesUsersSinceFilter` with another filter by using `or`, as follows:
|
||||
|
||||
[source,xml]
|
||||
----
|
||||
@@ -189,36 +187,36 @@ The developer could then go onto combine the `activesUsersSinceFilter` with anot
|
||||
[[bootstrap::snapshot::events]]
|
||||
== Snapshot Events
|
||||
|
||||
By default, _Spring Data for Pivotal GemFire_ uses Pivotal GemFire's Snapshot Services on startup to import data and shutdown
|
||||
to export data. However, you may want to trigger periodic, event-based snapshots, for either import or export
|
||||
from within your _Spring_ application.
|
||||
By default, Spring Data for Pivotal GemFire uses Pivotal GemFire's Snapshot Services on startup to import data and on shutdown
|
||||
to export data. However, you may want to trigger periodic, event-based snapshots, for either import or export,
|
||||
from within your Spring application.
|
||||
|
||||
For this purpose, _Spring Data for Pivotal GemFire_ defines two additional _Spring_ application events, extending _Spring's_
|
||||
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationEvent.html[ApplicationEvent]
|
||||
For this purpose, Spring Data for Pivotal GemFire defines two additional Spring application events, extending Spring's
|
||||
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationEvent.html[`ApplicationEvent`]
|
||||
class for imports and exports, respectively: `ImportSnapshotApplicationEvent` and `ExportSnapshotApplicationEvent`.
|
||||
|
||||
The two application events can be targeted at the entire Pivotal GemFire Cache, or individual Pivotal GemFire Regions. The constructors
|
||||
in these classes accept an optional Region pathname (e.g. "/Example") as well as 0 or more `SnapshotMetadata` instances.
|
||||
The two application events can be targeted at the entire Pivotal GemFire cache or individual Pivotal GemFire regions. The constructors
|
||||
in these classes accept an optional region pathname (such as `/Example`) as well as xero or more `SnapshotMetadata` instances.
|
||||
|
||||
The array of `SnapshotMetadata` is used to override the snapshot meta-data defined by `<gfe-data:snapshot-import>`
|
||||
and `<gfe-data:snapshot-export>` sub-elements in XML, which will be used in cases where snapshot application events
|
||||
do not explicitly provide `SnapshotMetadata`. Each individual `SnapshotMetadata` instance can define it's own
|
||||
The array of `SnapshotMetadata` overrides the snapshot metadata defined by `<gfe-data:snapshot-import>`
|
||||
and `<gfe-data:snapshot-export>` sub-elements, which are used in cases where snapshot application events
|
||||
do not explicitly provide `SnapshotMetadata`. Each individual `SnapshotMetadata` instance can define its own
|
||||
`location` and `filters` properties.
|
||||
|
||||
Import/export snapshot application events are received by all snapshot service beans defined in the _Spring_
|
||||
`ApplicationContext`. However, import/export events are only processed by "matching" Snapshot Service beans.
|
||||
All snapshot service beans defined in the Spring `ApplicationContext` receive import and export snapshot application events.
|
||||
However, only matching Snapshot Service beans process import and export events.
|
||||
|
||||
A Region-based `[Import|Export]SnapshotApplicationEvent` matches if the Snapshot Service bean defined
|
||||
is a `RegionSnapshotService` and it's Region reference (as determined by the `region-ref` attribute) matches
|
||||
the Region's pathname specified by the snapshot application event.
|
||||
A region-based `[Import|Export]SnapshotApplicationEvent` matches if the Snapshot Service bean defined
|
||||
is a `RegionSnapshotService` and its region reference (as determined by the `region-ref` attribute) matches
|
||||
the region's pathname, as specified by the snapshot application event.
|
||||
|
||||
A Cache-based `[Import|Export]SnapshotApplicationEvent` (i.e. a snapshot application event without a Region pathname)
|
||||
A Cache-based `[Import|Export]SnapshotApplicationEvent` (that is, a snapshot application event without a region pathname)
|
||||
triggers all Snapshot Service beans, including any `RegionSnapshotService` beans, to perform either an import or export,
|
||||
respectively.
|
||||
|
||||
It is very easy to use _Spring's_
|
||||
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationEventPublisher.html[ApplicationEventPublisher]
|
||||
interface to fire import and/or export snapshot application events from your application like so:
|
||||
You can use Spring's
|
||||
http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/ApplicationEventPublisher.html[`ApplicationEventPublisher`]
|
||||
interface to fire import and export snapshot application events from your applicationas follows:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
@@ -246,12 +244,11 @@ public class ExampleApplicationComponent {
|
||||
}
|
||||
----
|
||||
|
||||
In this particular example, only the "/Example" Region's Snapshot Service bean will pick up and handle the export event,
|
||||
saving the filtered, "/Example" Region's data to the "data.snapshot" file in a sub-direcrtory
|
||||
In the preceding example, only the `/Example` region's Snapshot Service bean picks up and handles the export event,
|
||||
saving the filtered, `/Example` region's data to the `data.snapshot` file in a sub-direcrtory
|
||||
of the application's working directory.
|
||||
|
||||
Using _Spring_ application events and messaging subsystem is a good way to keep your application loosely coupled.
|
||||
It is also not difficult to imagine that the snapshot application events could be fired on a periodic basis
|
||||
using _Spring's_
|
||||
Using the Spring application events and messaging subsystem is a good way to keep your application loosely coupled.
|
||||
You can also use Spring's
|
||||
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#scheduling-task-scheduler[Scheduling]
|
||||
services.
|
||||
services to fire snapshot application events on a periodic basis.
|
||||
|
||||
Reference in New Issue
Block a user