From 6f8355e233dd043d94d5a2fe920d52df5a9acfc2 Mon Sep 17 00:00:00 2001 From: John Blum Date: Wed, 4 Oct 2017 11:16:20 -0700 Subject: [PATCH] DATAGEODE-47 - Add documentation in SDG's Reference Guide for the new Annotation-based configuration model. --- src/main/asciidoc/index.adoc | 1 + .../reference/bootstrap-annotations.adoc | 2089 +++++++++++++++++ src/main/asciidoc/reference/data.adoc | 2 +- 3 files changed, 2091 insertions(+), 1 deletion(-) create mode 100644 src/main/asciidoc/reference/bootstrap-annotations.adoc diff --git a/src/main/asciidoc/index.adoc b/src/main/asciidoc/index.adoc index 86172010..6ffaea5e 100644 --- a/src/main/asciidoc/index.adoc +++ b/src/main/asciidoc/index.adoc @@ -34,6 +34,7 @@ include::{basedocdir}/introduction/new-features.adoc[] 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[] diff --git a/src/main/asciidoc/reference/bootstrap-annotations.adoc b/src/main/asciidoc/reference/bootstrap-annotations.adoc new file mode 100644 index 00000000..aadc3bc8 --- /dev/null +++ b/src/main/asciidoc/reference/bootstrap-annotations.adoc @@ -0,0 +1,2089 @@ +[[bootstrap-annotation-config]] += Bootstrapping Apache Geode using Spring Annotations + +_Spring Data Geode_ (SDG) 2.0 introduces a **new** Annotation-based configuration model to bootstrap Apache Geode +with the Spring container. + +The primary motivation for introducing an Annotation-based approach to the configuration of Apache Geode in +a Spring context is to enable application developers to _**get up and running** as **quickly** and as **easily** +as possible_. + +[[bootstrap-annotation-config-introduction]] +== Introduction + +Apache Geode can be very difficult to setup and use successfully given all the +http://geode.apache.org/docs/guide/12/reference/topics/gemfire_properties.html[configuration properties], +configuration options +(http://geode.apache.org/docs/guide/12/reference/topics/chapter_overview_cache_xml.html[cache.xml], +http://geode.apache.org/docs/guide/12/tools_modules/gfsh/chapter_overview.html[_Gfsh_] ++ http://geode.apache.org/docs/guide/12/configuring/chapter_overview.html[_Cluster Configuration_], +<>) +along with different supported _topologies_ +(http://geode.apache.org/docs/guide/12/topologies_and_comm/cs_configuration/chapter_overview.html[client/server], +http://geode.apache.org/docs/guide/12/topologies_and_comm/p2p_configuration/chapter_overview.html[P2P], +http://geode.apache.org/docs/guide/12/topologies_and_comm/multi_site_configuration/chapter_overview.html[WAN]) +and https://cwiki.apache.org/confluence/display/GEODE/Geode+Internal+Architecture?src=contextnavpagetreemode[_Distributed System Design Patterns_] +(e.g. shared-nothing architecture). The Annotation-based configuration model aims to simplify all this plus more. + +The Annotation-based configuration model is an alternative to XML-based configuration using _Spring Data Geode's_ +XML Namespace. With XML, an application developer would use the `spring-gemfire` (`gfe`) schema for configuration +and the `spring-data-gemfire` (`gfe-data`) schema for data access related concerns. See <> for more details. + +NOTE: As of SDG 2.0, the new Annotation-based configuration model does not yet have configuration support +for Apache Geode's WAN components and topology. + +Like _Spring Boot_, _Spring Data Geode's_ Annotation-based configuration model was designed as an opinionated, +_convention over configuration_ approach for using Apache Geode. Indeed, the Annotation-based configuration model +was inspired by _Spring Boot_ as well as several other Spring and _Spring Data_ projects. + +By following convention, all Annotations provide reasonable and sensible defaults for all the attributes out-of-the-box. +The default value for a given Annotation attribute directly corresponds to the default value provided in Apache Geode +for the same configuration property or setting. + +The intention is to let an application developer enable an Apache Geode feature or an embedded service by simply +declaring the Annotation on his/her Spring `@Configuration` or `@SpringBootApplcation` class without needing to +unnecessarily configure a large number of attributes or properties just to use the feature. + +Again, _getting up and running as quickly and as easily as possible_ is the primary objective. + +However, the option to customize the configuration meta-data and behavior of Apache Geode is there should an application +developer need it and _Spring Data Geode's_ Annotation-based configuration will quietly back away. The application +developer simply just needs to specify the configuration attributes s/he wishes to adjust. And, as we will see below, +there are several ways to configure an Apache Geode feature or embedded service using Annotations. + +All the **new** SDG Annotations can be found in the `org.springframework.data.gemfire.config.annotation` package. + +[[bootstrap-annotation-config-geode-applications]] +== Bootstrapping Apache Geode applications with Spring + +Like all _Spring Boot_ applications that begin by annotating the application class with `@SpringBootApplication`, +a _Spring Boot_ application can easily become an Apache Geode cache application simply by declaring +1 of 3 main Annotations: + +1. `@ClientCacheApplication` +2. `@PeerCacheApplication` +3. `@CacheServerApplication` + +These 3 Annotations are the Spring/Apache Geode application developer's starting point. + +To realize the intent behind these Annotations, a user must understand that there are 2 types of cache instances +that can be created with Apache Geode: a _client_ or a _peer_. + +A _Spring Boot_ application can be configured as an Apache Geode cache client (i.e. with an instance of `ClientCache`), +which communicates with an existing, standalone cluster of Apache Geode servers used to manage the application's data. +The _client/server_ topology is the most typical system architecture employed when using Apache Geode and the user +can make her _Spring Boot_ application a cache client simply by annotating it with `@ClientCacheApplication`. + +Alternatively, a _Spring Boot_ application may be a peer member of an Apache Geode cluster. That is, the application +itself is just another server in the cluster of servers that will manage data. The application creates an "embedded" +peer `Cache` instance when a developer annotates his/her application class with `@PeerCacheApplication`. + +By extension, the application may also serve as a `CacheServer` for cache clients, allowing clients to connect +and perform data access operations on the server. This is accomplished by annotating the application class with +`@CacheServerApplication` in place of `@PeerCacheApplication`, which will create a peer `Cache` instance along with +the `CacheServer`. + +NOTE: An Apache Geode Server is not necessarily a "_Cache Server_" by default. That is, it is not necessarily setup to +service cache clients just because it is a "server". A Geode Server can just be a peer member/data node of the cluster +that manages data without servicing any clients while other peer members in the cluster are setup to service +clients in addition to managing data. It also possible to setup certain peer members as non-data node, +http://geode.apache.org/docs/guide/12/developing/region_options/data_hosts_and_accessors.html[data accessors] +that can service clients as `CacheServers` as well, but is well beyond the scope of this document. + +By way of example, if I wanted to create a _Spring Boot_, Apache Geode cache client application, I would start with... + +.Spring-based Apache Geode `ClientCache` application +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +class ClientApplication { .. } +---- + +And, if I wanted to create a _Spring Boot_ application with an embedded peer `Cache` instance, where my application +will be a server and peer member of a cluster, or distributed system formed by Apache Geode, then I would start with... + +.Spring-based Apache Geode embedded peer `Cache` application +[source, java] +---- +@SpringBootApplication +@PeerCacheApplication +class ServerApplication { .. } +---- + +Alternatively, a user may use the `@CacheServerApplication` annotation in place of `@PeerCacheApplication`, +which will create both an "embedded" peer `Cache` instance along with a `CacheServer` running on "_localhost_", +listening on the default cache server port, *40404*... + +.Spring-based Apache Geode embedded `CacheServer` Application +[source, java] +---- +@SpringBootApplication +@CacheServerApplication +class ServerApplication { .. } +---- + +[[bootstrap-annotation-config-client-server-applications]] +== Going in-detail on _client/server_ applications + +There are multiple ways that a client can connect to and communicate with servers in a Geode cluster. The most common +and recommended approach is to use Apache Geode Locators. + +NOTE: A cache client can connect to 1 or more Locators in the Geode cluster instead of directly to a +`CacheServer`. The advantage of using Locators over direct `CacheServer` connections is that Locators provide meta-data +about the cluster to which clients are connected. This meta-data includes information like which servers have the least +amount of load, or which servers contain the data of interests to the client. A Locator also provides fail-over +capabilities in case a `CacheServer` goes down. By enabling the PR single-hop capability in the client `Pool`, +the client is routed directly to the server containing the data the client needs access to. + +NOTE: Locators are also peer members in a cluster. Locators actually constitute what makes up a cluster of Geode nodes; +i.e. all nodes connected by a Locator make up a cluster of peers and new members use Locators to join a cluster +and find other members. + +Since Apache Geode sets up a "DEFAULT" `Pool` connected to a `CacheServer` running on "_localhost_", listening on port +**40404** by default when a `ClientCache` instance is created, there is nothing special a user need do to utilize +the _client/server_ topology. Simply annotate your server-side _Spring Boot_ application with +`@CacheServerApplication` and your client-side _Spring Boot_ application with `@ClientCacheApplication` +and you are all set. + +You can even start your servers using _Gfsh's_ `start server` command if you prefer. Your _Spring Boot_ +`@ClientCacheApplication` will still connect to the server regardless of how it is started. Although, we think you +will prefer to configure and start your servers using the _Spring Data Geode_ approach, with Annotations. + +However, as an application developer, you will no doubt want to customize the "DEFAULT" `Pool` setup by Apache Geode +to possibly connect to 1 or more Locators, for instance... + +.Spring-based Apache Geode `ClientCache` application using Locators +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication(locators = { + @Locator(host = "boombox" port = 11235), + @Locator(host = "skullbox", port = 12480) +}) +class ClientApplication { .. } +---- + +Along with the `locators` attribute, the `@ClientCacheApplication` annotation has a `servers` attribute that can be used +to specify 1 or more nested `@Server` annotations that enable the cache client to connect directly to 1 or more servers. + +NOTE: You can only use either the `locators` or `servers` attribute, but not both, which is enforced by Apache Geode. + +A user may also configure additional `Pools`, other than the "DEFAULT" `Pool` provided by Apache Geode when +a `ClientCache` instance is created with the `@ClientCacheApplication` annotation, by using the `@EnablePool` +and `@EnablePools` annotations. + +NOTE: `@EnablePools` is a composite annotation that aggregates several nested `@EnablePool` annotations on +a single class. Java 8 and earlier does not allow more than 1 annotation of the same type to be declared on a class. + +.Spring-based Apache Geode `ClientCache` application using multiple named `Pools` +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication(logLevel = "info") +@EnablePool(name = "VenusPool", servers = @Server(host = "venus", port = 48484), + min-connections = 50, max-connections = 200, ping-internal = 15000, + prSingleHopEnabled = true, readTimeout = 20000, retryAttempts = 1, + subscription-enable = true) +@EnablePools(pools = { + @EnablePool(name = "SaturnPool", locators = @Locator(host="skullbox", port=20668), + subsription-enabled = true), + @EnablePool(name = "NeptunePool", severs = { + @Server(host = "saturn", port = 41414), + @Server(host = "neptune", port = 42424) + }, min-connections = 25)) +}) +class ClientApplication { .. } +---- + +The `name` attribute is the only required attribute of the `@EnablePool` annotation. As we will see below, the value +of `name` corresponds to both the name of the `Pool` bean created in the Spring context as well as the name used to +reference the corresponding configuration properties. It is also the name of the `Pool` registered and used +in Apache Geode. + +Similarly, on the server, a user can configure multiple `CacheServers` that a client can connect to... + +.Spring-based Apache Geode `CacheServer` application using multiple named `CacheServers` +[source, java] +---- +@SpringBootApplication +@CacheSeverApplication(logLevel = "info", autoStartup = true, maxConnections = 100) +@EnableCacheServer(name = "Venus", autoStartup = true, + hostnameForClients = "venus", port = 48484) +@EnableCacheServers(servers = { + @EnableCacheServer(name = "Saturn", hostnameForClients = "saturn", port = 41414), + @EnableCacheServer(name = "Neptune", hostnameForClients = "neptune", port = 42424) +}) +class ServerApplication { .. } +---- + +NOTE: Like `@EnablePools`, `@EnableCacheServers` is a composite annotation for aggregating multiple `@EnableCacheServer` +annotations on a single class. + +One thing an observant reader may have noticed is, in all cases, the user is specifying hard-coded values for hostnames, +ports as well other configuration-oriented Annotation attributes. This is not ideal when a user's application gets +promoted and deployed to different environments, such as from DEV to QA to STAGING to PROD. + +How does an application developer handle dynamic configuration determined at runtime? + +[[bootstrap-annotation-config-configurers]] +== Runtime configuration using `Configurers` + +Another goal when designing the Annotation-based configuration model was to preserve _Type-Safety_ in the Annotation +attributes. For example, if an attribute could be expressed as an `int`, like a port number, then the attribute's type +should be an `int`. + +Unfortunately, this is not conducive to dynamic and resolvable configuration at runtime. + +One of the finer features of Spring is the ability to use _property placeholders_ or _SpEL expressions_ in properties +or attributes of the configuration meta-data when configuring beans in a Spring context. Although, this would require +all Annotation attributes be `Strings` thereby giving up _Type-Safety_; not acceptable! + +So, _Spring Data Geode_ borrows from another commonly used pattern in Spring, `Configurers`. Many different +`Configurer` interfaces are provided out-of-the-box in Spring Web MVC, such as the +https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/config/annotation/ContentNegotiationConfigurer.html[`org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer`]. + +`Configurers` are a way to allow application developers to receive a callback and customize the configuration of a +component on startup. The framework calls back to user-provided code to adjust the configuration at runtime. One of +the more common uses of this pattern is to supply conditional configuration based on the application's +runtime environment. + +_Spring Data Geode_ provides several `Configurer` callback interfaces to customize different aspects of Annotation-based +configuration meta-data at runtime, before the _Sring_ managed beans that the Annotations create are initialized: + +* `ClientCacheConfigurer` +* `PeerCacheConfigurer` +* `CacheServerConfigurer` +* `ContinuousQueryListenerContainerConfigurer` +* `DiskStoreConfigurer` +* `IndexConfigurer` +* `PoolConfigurer` +* `RegionConfigurer` + +For example, we can use the `CacheServerConfigurer` and `ClientCacheConfigurer` to customize the port numbers +used by our `CacheServer` and `ClientCache` applications, respectively. + +First, in our server application... + +.Customizing a Spring Boot `CacheServer` application with a `CacheServerConfigurer` +[source, java] +---- +@SpringBootApplication +@CacheServerApplication(name = "SpringApplication", logLevel = "info") +class ServerApplication { + + @Bean + CacheServerConfigurer cacheServerPortConfigurer( + @Value("${geode.cache.server.host:localhost}") String cacheServerHost + @Value("${geode.cache.server.port:40404}") int cacheServerPort) { + + return (beanName, cacheServerFactoryBean) -> { + cacheServerFactoryBean.setBindAddress(cacheServerHost); + cacheServerFactoryBean.setHostnameForClients(cacheServerHost); + cacheServerFactoryBean.setPort(cacheServerPort); + }; + } +} +---- + +Then, in our client application... + +.Customizing a Spring Boot `ClientCache` application with a `ClientCacheConfigurer` +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication(logLevel = "info") +class ClientApplication { + + @Bean + ClientCacheConfigurer clientCachePoolPortConfigurer( + @Value("${geode.cache.server.host:localhost}") String cacheServerHost + @Value("${geode.cache.server.port:40404}") int cacheServerPort) { + + return (beanName, clientCacheFactoryBean) -> + clientCacheFactoryBean.setServers(Collections.singletonList( + new ConnectionEndpoint(cacheServerHost, cacheServerPort))); + } +} +---- + +By using the provided `Configurers`, a user is able to receive a callback in order to further customize +the configuration that is enabled by the associated Annotation. + +In addition, when the `Configurer` is declared as a bean in the Spring context, the bean definition can take advantage +of other Spring container features, such as _property placeholders_, or _SpEL expressions_ in `@Value` annotations +on factory method parameters, and so on. + +All _Spring Data Geode_-provided `Configurers` take 2 bits of information in the callback: the name of the bean created +in the Spring context by the Annotation along with a reference to the `FactoryBean` used by the Annotation to +configure the Geode component (e.g. a `ClientCache` instance with SDG's `ClientCacheFactoryBean`). + +NOTE: SDG `FactoryBeans` are part of the SDG public API and are what an application developer would use in Spring's +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-java[Java-based container configuration] +if this **new** Annotation-based configuration model were not provided. Indeed, the Annotations themselves are using +these very same `FactoryBeans` for their configuration. + +Given a `Configurer` can be declared as a regular bean definition like any other, it is not difficult to imagine +a user combining different Spring configuration options, such as the use of _Spring Profiles_ with `Conditions` +as well as other features to create even more sophisticated and flexible configuration. + +However, `Configurers` are not the only option. + +[[bootstrap-annotation-config-properties]] +== Runtime configuration using `Properties` + +In addition to `Configurers`, each Annotation attribute in the Annotation-based configuration model is associated +with a corresponding configuration _property_, prefixed with `spring.data.gemfire.`, that can be declared in +_Spring Boot_ `application.properties`. + +Building on our examples above, the client's `application.properties` would define... + +.Client `application.properties` +[source, java] +---- +spring.data.gemfire.cache.log-level=info +spring.data.gemfire.cache.pool.venus.servers=venus[48484] +spring.data.gemfire.cache.pool.venus.max-connections=200 +spring.data.gemfire.cache.pool.venus.min-connections=50 +spring.data.gemfire.cache.pool.venus.ping-interval=15000 +spring.data.gemfire.cache.pool.venus.pr-single-hop-enabled=true +spring.data.gemfire.cache.pool.venus.read-timeout=20000 +spring.data.gemfire.cache.pool.venus.subscription-enabled=true +spring.data.gemfire.cache.pool.saturn.locators=skullbox[20668] +spring.data.gemfire.cache.pool.saturn.subscription-enabled=true +spring.data.gemfire.cache.pool.neptune.servers=saturn[41414],neptune[42424] +spring.data.gemfire.cache.pool.neptune.min-connections=25 +---- + +And, the server's application.properties would define... + +.Server `application.properties` +[source, java] +---- +spring.data.gemfire.cache.log-level=info +spring.data.gemfire.cache.server.port=40404 +spring.data.gemfire.cache.server.Venus.port=43434 +spring.data.gemfire.cache.server.Saturn.port=41414 +spring.data.gemfire.cache.server.Neptune.port=41414 +---- + +Then, we can simplify the `@ClientCacheApplication` class to... + +.Spring `@ClientCacheApplication` class +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnablePools(pools = { + @EnablePool(name = "VenusPool"), + @EnablePool(name = "SaturnPool"), + @EnablePool(name = "NeptunePool") +}) +class ClientApplication { .. } +---- + +And, the `@CacheServerApplication` class as... + +.Spring `@CacheServerApplication` class +[source, java] +---- +@SpringBootApplication +@CacheServerApplication(name = "SpringApplication") +@EnableCacheServers(servers = { + @EnableCacheServer(name = "Venus"), + @EnableCacheServer(name = "Saturn"), + @EnableCacheServer(name = "Neptune") +}) +class ServerApplication { .. } +---- + +The example above illustrates why it is import to "name" your Annotation-based beans (other than it is required +in certain cases). Doing so makes it possible to reference the bean in a Spring context from XML, properties +and even Java. It is even possible to inject Annotation-defined beans into an application class, +for whatever purpose; for example... + +[source, java] +---- +@Component +class MyApplicationComponent { + + @Resource(name = "Saturn") + CacheServer saturnCacheServer; + + ... +} +---- + +Likewise, naming a Annotated-defined bean allows you to code a `Configurer` to customize a specific, "named" bean +since the `beanName` is 1 of 2 arguments passed to the callback. + +Often times, an associated Annotation attribute property takes 2 forms: a "named" property along with +an "unnamed" property. + +For example... + +[source, java] +---- +spring.data.gemfire.cache.server.bind-address=10.105.20.1 +spring.data.gemfire.cache.server.Venus.bind-address=10.105.20.2 +spring.data.gemfire.cache.server.Saturn... +spring.data.gemfire.cache.server.Neptune... +---- + +While there are 3 named `CacheServers` above, there is 1 unnamed `CacheServer` property that serves as the default +value for any unspecified value for that property even for "named" `CacheServers`. So, while "Venus" sets +and overrides its own `bind-address`, "Saturn" and "Neptune" inherit from the unnamed +`spring.data.gemfire.cache.server.bind-address` property. + +Refer to an Annotation's _Javadoc_ for which Annotation attributes support property-based configuration, and whether +they support "named" properties over just "default", unnamed properties. + +[[bootstrap-annotation-config-properties-of-properties]] +=== `Properties` of `Properties` + +Of course, in Spring fashion, you can even express `Properties` in terms of other `Properties`, whether that is +using a _Spring Boot_ `application.properties` file or by using the `@Value` annotation in your Java class... + +.Properties of Properties +[source, java] +---- +spring.data.gemfire.cache.server.port=${geode.cache.server.port:40404} +---- + +Or, in Java... + +[source, java] +---- + @Bean + CacheServerConfigurer cacheServerPortConfigurer( + @Value("${geode.cache.server.port:${some.other.property:40404}}") int cacheServerPort) { + + ... + } +} +---- + +Property placeholder nesting can be arbitrarily deep. + +[[bootstrap-annotation-config-embedded-services]] +== Configuring embedded services + +Apache Geode provides the ability to start many different embedded services required by an application depending on +the use case. + +[[bootstrap-annotation-config-embedded-services-locator]] +=== Configuring an embedded Locator + +As mentioned previously, Apache Geode Locators are used by clients to connect with and find servers in a cluster +as well as by new members joining an existing cluster to find other peers. + +It is often convenient for application developers as they are developing their _Spring Boot_, _Spring Data Geode_ +applications to startup up a small cluster of 2 or 3 Apache Geode servers. Rather than starting a separate Locator +process, a user can simply annotate her `@CacheServerApplication` class with `@EnableLocator`. + +.Spring, Apache Geode `CacheServer` application running an embedded Locator +[source, java] +---- +@SpringBootApplication +@CacheServerApplication +@EnableLocator +class ServerApplication { .. } +---- + +The `@EnableLocator` annotation starts and embedded Locator in the Spring, Apache Geode `CacheServer` application +process running on "_localhost_", listening on the default Locator port **10334**. It is possible to customize +the `host` (a.k.a bind address) and `port` that the embedded Locator binds to using the corresponding +Annotation attributes. + +Then, it is possible to start other _Spring Boot_, `@CacheServerApplication` enabled applications connecting to this +Locator with... + +.Spring, Apache Geode `CacheServer` application connecting to a Locator +[source, java] +---- +@SpringBootApplication +@CacheServerApplication(locators = "localhost[10334]") +class ServerApplication { .. } +---- + +You may even combine both application classes shown above into a single class and use your IDE feature to create +different run profile configurations to create and run different instances of the same class with slightly modified +configuration using Java System Properties... + +.Spring `CacheServer` application running an embedded Locator and connecting to the Locator +[source, java] +---- +@SpringBootApplication +@CacheServerApplication(locators = "localhost[10334]") +public class ServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ServerApplication.class); + } + + @EnableLocator + @Profile("embedded-locator") + static class Configuration { + } +} +---- + +Then, for each run profile, a user simply sets and changes the following System properties... + +.IDE run profile configuration +[source, java] +---- +spring.data.gemfire.cache.name=SpringCacheServerOne +spring.data.gemfire.cache.server.port=41414 +spring.profiles.active=embedded-locator +---- + +Only 1 of the run profiles for the `ServerApplication` class should be set with the +`-Dspring.profiles.active=embedded-locator` Java System Property. Then, simply change the `name` and `cache.server.port` +for each of the other run profiles and you'll have yourself a small cluster/distributed system of Geode Servers. + +NOTE: The `@EnableLocator` annotation was meant to be a development-time annotation only and not something +an application developer should use in production. It is recommended that Locators be stand-alone, independent +processes in the cluster. + +More details on how Apache Geode Locators work can be found +http://geode.apache.org/docs/guide/12/topologies_and_comm/topology_concepts/how_member_discovery_works.html[here]. + +[[bootstrap-annotation-config-embedded-services-manager]] +=== Configuring an embedded Manager + +An Apache Geode Manager is another peer member/node in the cluster that is responsible for "management" activities. +Management activities include things like creating Regions, Indexes, DiskStores, etc. The Manager allows a JMX-enabled +client (e.g. _Gfsh_ shell tool) to connect to the manager to manage the cluster. It is also possible to connect to +a Manager with JDK provided tools like _JConsole_ or _JVisualVM_, given these are both JMX-enabled clients as well. + +Perhaps we would also like to make our Spring `@CacheServerApplication` shown above a Manager as well. Simply annotate +your Spring `@Configurtion` or `@SpringBootApplication` class with `@EnableManager` and you are done. By default, +the Manager binds to "_localhost_" listening on the default Apache Geode Manager port **1099**. Several aspects of +the Manager can be configured with the Annotation attributes or corresponding properties. + +.Spring `CacheServer` application running an embedded Manager +[source, java] +---- +@SpringBootApplication +@CacheServerApplication(locators = "localhost[10334]") +public class ServerApplication { + + public static void main(String[] args) { + SpringApplication.run(ServerApplication.class); + } + + @EnableLocator + @EnableManager + @Profile("embedded-locator-manager") + static class Configuration { + } +} +---- + +With the above class, you can even use _Gfsh_ to connect to this server and manage it. + +[source, java] +---- +$ gfsh + _________________________ __ + / _____/ ______/ ______/ /____/ / + / / __/ /___ /_____ / _____ / + / /__/ / ____/ _____/ / / / / +/______/_/ /______/_/ /_/ 1.2.1 + +Monitor and Manage Apache Geode + +gfsh>connect +Connecting to Locator at [host=localhost, port=10334] .. +Connecting to Manager at [host=10.99.199.5, port=1099] .. +Successfully connected to: [host=10.99.199.5, port=1099] + +gfsh>list members + Name | Id +---------------------- | ---------------------------------------------------- +SpringCacheServerOne | 10.99.199.5(SpringCacheServerOne:14842):1024 +SpringCacheServerTwo | 10.99.199.5(SpringCacheServerTwo:14844):1025 +SpringCacheServerThree | 10.99.199.5(SpringCacheServerThree:14846):1026 +---- + +Because we also have the embedded Locator enabled, we were able to connect indirectly to the Manager through +the Locator. The Locator allows JMX clients to connect and find a Manager node in the cluster. If none exist, +the Locator will assume the role of the Manager. However, if no Locator existed, then we would need to connect +directly to the Manager using... + +.Gfsh `connect` command connecting directly to the Manager +[source, java] +---- +gfsh>connect --jmx-manager=localhost[1099] +---- + +NOTE: Like the `@EnableLocator` annotation, the `@EnableManager` annotation was also meant to be a development-time +only and not something an application developer should use in production. It is recommended that Managers, +like Locators, be stand-alone, independent processes in the cluster. + +More details on Apache Geode Management and Monitoring can be found +http://geode.apache.org/docs/guide/12/managing/book_intro.html[here]. + +[[bootstrap-annotation-config-embedded-services-http]] +=== Configuring the embedded HTTP Server + +Apache Geode is also capable of running an embedded HTTP server. The current implementation is backed by +https://www.eclipse.org/jetty/[Eclipse Jetty]. + +The embedded HTTP server is used to host Apache Geode's Management (Admin) REST API (not a publicly advertised API), +the http://geode.apache.org/docs/guide/12/rest_apps/book_intro.html[Developer REST API] +and the http://geode.apache.org/docs/guide/12/tools_modules/pulse/pulse-overview.html[Pulse Monitoring Web Application]. + +However, to use any of these Apache Geode provided Web applications, you must have a full installation of Apache Geode +installed on your system, and you must set the `GEMFIRE` environment variable to your installation directory. + +To enable the embedded HTTP server, simply add the `@EnableHttpService` annotation to any `@PeerCacheApplication` +or `@CacheServerApplication` annotated class... + +.Spring `CacheServer` application running an embedded HTTP server +[source, java] +---- +@SpringBootApplication +@CacheServerApplication +@EnableHttpService +public class ServerApplication { .. } +---- + +By default, the embedded HTTP server listens on port **7070** for HTTP client requests. Of course, you can use +the Annotation attributes or corresponding configuration properties to adjust the configuration as needed. + +Follow the links above for more details on HTTP support. + +[[bootstrap-annotation-config-embedded-services-memcached]] +=== Configuring the embedded Memcached Server (Gemcached) + +Apache Geode also implements the Memcached protocol with the ability to service Memcached clients. That is Memcached +clients can connect to an Apache Geode cluster and perform Memcached operations as if the Apache Geode Servers +in the cluster were actual Memcached Servers. + +To enable the embedded Memcached Service, simply add the `@EnableMemcachedServer` annotation to any +`@PeerCacheApplication` or `@CacheServerApplication` annotated class... + +.Spring `CacheServer` application running an embedded Memcached Server +[source, java] +---- +@SpringBootApplication +@CacheServerApplication +@EnabledMemcachedServer +public class ServerApplication { .. } +---- + +More details on Apache Geode's _Gemcached_ service can be found +http://geode.apache.org/docs/guide/12/tools_modules/gemcached/chapter_overview.html[here]. + +[[bootstrap-annotation-config-embedded-services-redis]] +=== Configuring the embedded Redis Server + +Apache Geode also implements the Redis Server protocol, which enables Redis clients to communicate with a cluster +of Apache Geode Servers and issue Redis commands. As of this writing, the Redis Server protocol support in Apache Geode +is still experimental. + +To enable the embedded Redis Service, simply add the `@EnableRedisServer` annotation to any `@PeerCacheApplication` +or `@CacheServerApplication` annotated class... + +.Spring `CacheServer` application running an embedded Redis Server +[source, java] +---- +@SpringBootApplication +@CacheServerApplication +@EnableRedisServer +public class ServerApplication { .. } +---- + +More details on Apache Geode's Redis Adapter can be found +http://geode.apache.org/docs/guide/12/tools_modules/redis_adapter.html[here]. + +[[bootstrap-annotation-config-logging]] +== Configuring Logging + +Often times it is necessary to turn up logging in order to understand exactly what Apache Geode is doing and when. + +To enable _Logging_, simply annotate your application class with `@EnableLogging` and set the appropriate attributes +or associated properties... + +.Spring `ClientCache` application with Logging enabled +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableLogging(logLevel="info", logFile="/absolute/file/system/path/to/application.log) +public class ClientApplication { .. } +---- + +While the `logLevel` attribute can be specified with all the cache-based application annotations +(e.g. `@ClientCacheApplication(logLevel="info")`), it is easier to customize logging behavior with +the `@EnableLogging` annotation. + +See the `@EnableLogging` annotation _Javadoc_ for more details. + +[[bootstrap-annotation-config-statistics]] +== Configuring Statistics + +To gain even deeper insight into Apache Geode during runtime, an application developer can enable _Statistics_. +Gathering statistical data facilitates system analysis and troubleshooting when complex problems occur, which +are often distributed in nature and timing is a factor. + +When _Statistics_ are enabled, a user can use Apache Geode's +http://gemfire.docs.pivotal.io/gemfire/tools_modules/vsd/chapter_overview.html[VSD (_Visual Statistics Display_)] tool +to analyze the statistical data that is collected. + +To enable _Statistics_, simply annotate your application class with `@EnableStatistics`... + +.Spring `ClientCache` application with Statistics enabled +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableStatistics +public class ClientApplication { .. } +---- + +Enabling _Statistics_ on a server is particularly valuable when evaluating performance, which is as simple as +annotating your `@PeerCacheApplication` or `@CacheServerApplication` class with `@EnableStatistics`. + +Use the `@EnableStatistics` annotation attributes or associated properties to customize the _Statistics_ gathering +and collection process. + +See the `@EnableStatistics` annotation _Javadoc_ for more details. + +More details on Apache Geode's _Statistics_ can be found +http://gemfire.docs.pivotal.io/gemfire/managing/statistics/chapter_overview.html[here]. + +[[bootstrap-annotation-config-pdx]] +== Configuring PDX + +One of the more powerful features of Apache Geode is +http://geode.apache.org/docs/guide/12/developing/data_serialization/gemfire_pdx_serialization.html[PDX Serialization]. +While a complete discussion on PDX is well beyond the scope of this document, serialization using PDX is a much better +alternative to _Java Serialization_, with the following benefits... + +1. PDX uses a centralized _Type Registry_ to keep the serialized bytes of an object more compact. +2. PDX is a neutral serialization format allowing both Java and Native Clients to operate on the same data set. +3. PDX supports versioning and allows object fields to be added or removed with affecting applications using either +older or newer versions of the PDX serialized, application domain object types that change, without data loss. +4. PDX allows object fields to be accessed individually or in OQL query projections and predicates without +the object needing to be de-serialized first. + +In general, serialization in Apache Geode is needed anytime data is transferred to/from clients and servers or between +peers in a cluster for normal distribution and replication processes as well as when data is overflowed or persisted +to disk. + +To enable PDX, simply annotate your application class with `@EnablePdx`... + +.Spring `ClientCache` application with PDX enabled +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnablePdx +public class ClientApplication { .. } +---- + +Typically, an application's domain object types will either implement the +http://geode.apache.org/releases/latest/javadoc/org/apache/geode/pdx/PdxSerializable.html[`org.apache.geode.pdx.PdxSerializable`] +interface, or an application developer will choose to implement and register the non-invasive +http://geode.apache.org/releases/latest/javadoc/org/apache/geode/pdx/PdxSerializer.html[`org.apache.geode.pdx.PdxSerializer`] +interface to handle the application domain object types that need to be serialized. + +Unfortunately, Apache Geode only allows one `PdxSerializer` to be registered, which suggests that all application +domain object types should be handled by a "single" `PdxSerializer` instance. But, that is a serious anti-pattern +and foolish practice to be sure. + +Even though only a single `PdxSerializer` instance can be registered with Apache Geode, it makes sense to create a +`PdxSerializer` implementation per application domain object type. + +By using the https://en.wikipedia.org/wiki/Composite_pattern[Composite Software Design Pattern], the application +developer can provide an implementation of the `PdxSerializer` interface that aggregates of all application +domain object type-specific `PdxSerializer` instances but acts as a single `PdxSerializer` instance, and register it. + +You can declare this _Composite_ `PdxSerializer` as a managed bean in the Spring context and refer to this +_Composite_ `PdxSerializer` by bean name in the `@EnablePdx` annotation using the `serializerBeanName` attribute. +_Spring Data Geode_ will take care of registering it with Apache Geode on the user's behalf. + +.Spring `ClientCache` application with PDX enabled, using a custom, composite `PdxSerializer` +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnablePdx(serializerBeanName = "compositePdxSerializer") +public class ClientApplication { + + @Bean + PdxSerializer compositePdxSerializer() { + return new CompositePdxSerializerBuilder()... + } +} +---- + +It is also possible to declare Apache Geode's +http://geode.apache.org/releases/latest/javadoc/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[`org.apache.geode.pdx.ReflectionBasedAutoSerializer`] +as a bean definition in a Spring context. Alternatively, you can use _Spring Data Geode's_ more robust, +https://docs.spring.io/spring-data-gemfire/docs/current/api/org/springframework/data/gemfire/mapping/MappingPdxSerializer.html[`org.springframework.data.gemfire.mapping.MappingPdxSerializer`], +which uses _Spring Data_ mapping meta-data and infrastructure applied to the serialization process for more efficient +handling than reflection alone. + +Many other aspects and features of PDX can be adjusted with the `@EnablePdx` annotation attributes +or associated configuration properties. + +See the `@EnablePdx` annotation _Javadoc_ for more details. + +[[bootstrap-annotation-config-ssl]] +== Configuring SSL + +Equally important to serializing data to be transferred over-the-wire is securing the data while in transit. +Of course, the common way to accomplish this in _Java_ is using the _Secure Sockets Extension_ (SSE) +and _Transport Layer Security_ (TLS). + +To enable SSL, simply annotate your application class with `@EnableSsl` and set the necessary SSL configuration +attributes (e.g. keystores, usernames/passwords, etc)... + +.Spring `ClientCache` application with SSL enabled +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableSsl +public class ClientApplication { .. } +---- + +Different Apache Geode components: `GATEWAY`, `HTTP`, `JMX`, `LOCATOR`, `SERVER` can be individually configured +with SSL, or they can all be collectively configured all at once to use SSL using the `CLUSTER` enumerated value. + +It is easy to specify which Apache Geode components that the SSL configuration settings should applied to using +the nested `@EnableSsl` annotation `Component` enum... + +.Spring `ClientCache` application with SSL enabled by Aache Geode component +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableSsl(components = { GATEWAY, LOCATOR, SERVER }) +public class ClientApplication { .. } +---- + +In addition component-level SSL configuration, `ciphers`, `protocols` and `keystore`/`truststore` information can +also be specified using the corresponding Annotation attribute or associated configuration properties. + +See the `@EnableSsl` annotation _Javadoc_ for more details. + +More details on Apache Geode SSL support can be found +http://gemfire.docs.pivotal.io/geode/managing/security/ssl_overview.html[here]. + +[[bootstrap-annotation-config-gemfire-properties]] +== Configuring GemFire Properties + +While many of the http://geode.apache.org/docs/guide/12/reference/topics/gemfire_properties.html[gemfire.properties] +are conveniently encapsulated in and abstracted with an Annotation in the SDG Annotation-based configuration model, +the less commonly used _Geode Properties_ are still accessible from the `@EnableGemFireProperties` annotation. + +Using the `@EnableGemFireProperties` annotation on your application class is convenient and a nice alternative to +creating a `gemfire.properties` file or setting _Geode Properties_ as Java System properties on the command-line +when launching your application. + +TIP: It is recommended that these _Geode Properties_ be set in a `gemfire.properties` file when deploying +your application to production. But, at development-time, it can be convenient to set these properties individually, +as needed, for prototyping and/or testing purposes. + +A few examples of some of the less common _Geode Properties_ that a user usually need not worry about include, +but are not limited to: `ack-wait-threshold`, `disable-tcp`, `socket-buffer-size`, etc. + +To individually set any _Geode Property_, simply annotate your application class with `@EnableGemFireProperties` +and set the _Geode Properties_ you want to change from the default, out-of-the-box value set by Apache Geode... + +.Spring `ClientCache` application with specific _Geode Properties_ set +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableGemFireProperties(conflateEvents = true, socketBufferSize = 16384) +public class ClientApplication { .. } +---- + +Keep in mind, some of the _Geode Properties_ are client specific (e.g. `conflateEvents`) while others are +server specific (e.g. `distributedSystemId`, `enableNetworkPartitionDetection`, `enforceUniqueHost`, `memberTimeout`, +`redundancyZone`). + +More details on Apache Geode properties can be found +http://geode.apache.org/docs/guide/12/reference/topics/gemfire_properties.html[here]. + +[[bootstrap-annotation-config-regions]] +== Configuring Regions + +So far, outside of PDX, our discussion has centered around configuring Apache Geode's more administrative functions: +creating a cache instance, starting embedded services, enabling Logging, Statistics and SSL, using `gemfire.properties` +to affect very low-level configuration and behavior. While all these configuration options are important, none of them +relate directly to the application. In other words, we still need some place to store our application data and make it +generally available and accessible. + +Apache Geode organizes data in a cache into +http://geode.apache.org/docs/guide/12/basic_config/data_regions/chapter_overview.html[Regions]. You can think of a +Region as a table in a relational database. Generally, a Region should only store a single type of object making it +more conducive for building effective `Indexes`. We will talk about Indexing +<>. + +Previously, _Spring Data Geode_ users needed to explicitly define and declare the Regions used in their applications +to store data by writing very verbose Spring configuration meta-data, whether a user was using SDG's `FactoryBeans` +from the API in Spring's +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#beans-java[Java-based container configuration]... + +.Example Region bean definition using Spring Java-based container configuration +[source, java] +---- +@Configuration +class GeodeConfiguration { + + @Bean("Example") + PartitionedRegionFactoryBean exampleRegion(GemFireCache gemfireCache) { + + PartitionedRegionFactoryBean exampleRegion = + new PartitionedRegionFactoryBean<>(); + + exampleRegion.setCache(gemfireCache); + exampleRegion.setClose(false); + exampleRegion.setPersistent(true); + + return exampleRegion; + } + + ... +} +---- + +Or, using <>... + +.Example Region bean definition using the SDG XML Namespace +[source, xml] +---- + + ... + +---- + +While neither Java nor XML configuration is hard to do, it is cumbersome, especially if an application has a large +number of Regions that need to be defined. Many relational database-based applications can literally have 100s +or even 1000s of tables. + +Ugh! + +Now users can define and configure Regions based on their application domain objects (entities). No longer does +a user need to explicitly define `Region` bean definitions in Spring configuration meta-data, unless finer-grained +control is required. + +To simplify Region creation, _Spring Data Geode_ combines the use of SD _Repositories_ with the expressive power of +Annotation-based configuration using the **new** `@EnableEntityDefinedRegions` annotation. + +NOTE: Most _Spring Data_ application developers should already be familiar with the +https://docs.spring.io/spring-data/commons/docs/current/reference/html/#repositories[_Spring Data Repository_ abstraction] +and _Spring Data Geode's_ <> of the SD _Repository abstraction_, which +has been specifically customized to optimize data access operations for Apache Geode. + +First, an application developer starts by defining the application domain objects... + +.Application domain object type modeling a Book +[source, java] +---- +@Region("Books") +class Book { + + @Id + private ISBN isbn; + + private Author author; + + private Category category; + + private LocalDate releaseDate; + + private Publisher publisher; + + private String title; + +} +---- + +Next, the application developer would define a basic _Repository_ for `Books` by extending _Spring Data Commons_ +`org.springframework.data.repository.CrudRepository` interface... + +.Repository for Books +[source, java] +---- +interface BookRepository extends CrudRepository { .. } +---- + +The `org.springframe.data.repository.CrudRepository` is a Data Access Object (DAO) providing basic data access +operations (CRUD) along with support for simple queries (e.g. `findById(..)`). The user can define additional, +more sophisticated queries simply by declaring query methods on the _Repository_ interface +(e.g. `List findByAuthor(Author author);`). + +Under-the-hood, _Spring Data Geode_ provides an implementation of this interface when the Spring container is +bootstrapped. SDG will even implement the query methods defined by the user so long as the user follows simple +<>. + +Now, when a user defined the `Book` class, she also specified the Region in which instances of `Book` will be mapped +and stored by declaring the _Spring Data Geode_ mapping annotation, `@Region` on the entity's type. Of course, if +the entity type (i.e. `Book`) referenced in the type parameter of the _Repository_ interface (i.e. `BookRepository`) +is not annotated with `@Region`, the name is derived from the simple class name of the entity type (i.e. "Book"). + +_Spring Data Geode_ uses the mapping context containing mapping meta-data for all the entities defined in your +application to determine all the Regions that will be needed at runtime. + +To enable and use this feature, simply annotate the application class with `@EnableEntityDefinedRegions`... + +.Entity-defined Region Configuration +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableGemfireRepositories +@EnableEntityDefinedRegions(basePackages = "example.app.domain") +class ClientApplication { .. } +---- + +TIP: Creating Regions from entity classes is the most useful when using _Spring Data Repositories_ in your application. +_Spring Data Geode's_ _Repository_ support is enabled with the `@EnableGemfireRepositories` annotation. + +By default, the `@EnableEntityDefinedRegions` annotation will scan for entity classes recursively starting from +the package of the configuration class on which the `@EnableEntityDefinedRegions` annotation is defined. + +However, it is common to limit the search during the scan by setting the `basePackages` attribute with the package names +containing your application entity classes. + +Alternatively, a user can use the more type-safe `basePackageClasses` attribute for specifying the package to scan +by setting the attribute to an entity type in the package containing the entity's class, or by using a non-entity +placeholder class in the package specifically created for identifying the package to scan. For example... + +.Entity-defined Region Configuration using the Entity class type +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableGemfireRepositories +@EnableEntityDefinedRegions(basePackageClasses = { + example.app.books.domain.Book.class, + example.app.customers.domain.Customer.class +}) +class ClientApplication { .. } +---- + +In addition to specifying the location where to begin the scan, like Spring's `@ComponentScan` annotation, a user can +specify include and exclude filters with all the same semantics of the +`org.springframework.context.annotation.ComponentScan.Filter` annotation. + +See the `@EnableEntityDefinedRegion` annotation _Javadoc_ for more details. + +[[bootstrap-annotation-config-region-types]] +=== Configuring Type-specific Regions + +Apache Geode supports many different +http://geode.apache.org/docs/guide/12/developing/region_options/region_types.html[types of Regions]. +Each type corresponds to the Region's +http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/DataPolicy.html[`DataPolicy`], +which determines exactly how the data in the Region will be managed (e.g. distributed/replicated, etc). + +NOTE: Other configuration settings also can affect how data is managed like the Region's `scope`. +See http://geode.apache.org/docs/guide/12/developing/region_options/storage_distribution_options.html[Storage and Distribution Options] +in the Apache Geode User Guide for more details. + +When user annotate their application domain object types with the generic `@Region` mapping annotation, +_Spring Data Geode_ will decide which type of `Region` to create. SDG's default strategy takes the cache type into +consideration when determining the type of `Region` to create. + +For example, if the application was declared as a `ClientCache` using the `@ClientCacheApplication` annotation, +then SDG would create a client `PROXY` `Region`. Or, if the application was declared as a peer `Cache` using either the +`@PeerCacheApplication` or `@CacheServerApplication` annotations, then SDG would create a server `PARTITION` `Region`. + +Of course, an application developer is always able to override the default when necessary. To override the default +applied by _Spring Data Geode_, 4 new Region mapping annotations have been introduced: + +* `ClientRegion` +* `LocalRegion` +* `PartitionRegion` +* `ReplicateRegion` + +The `ClientRegion` mapping annotation is specific to client applications. All other Region mapping annotations +listed above can only be used in server applications. + +It is sometimes necessary for client applications to create and use "local-only" Regions, perhaps to aggregate data +from other Regions in order to analyze the data locally and carry out some function performed by the application +for the user. In this case, the data may not necessarily need to be distributed back to the server, not unless other +applications need access to the results. This Region might even be temporary and discarded after use, which could +be accomplished with Idle-Timeout (TTI) and Time-To-Live (TTL) expiration policies on the Region itself (NOTE: this is +independent of and different from "entry" TTI/TTL expiration policies). + +In any case, if a user wanted to create a local-only, client Region where the data is not gong to be distributed to +a corresponding Region with the same name on the server, the user would specify the `@ClientRegion` mapping annotation +and set the `shortcut` attribute to `ClientRegionShortcut.LOCAL`... + +.Spring `ClientCache` application with a local-only, client Region +[source, java] +---- +@ClientRegion(shortcut = ClientRegionShortcut.LOCAL) +class ClientLocalEntityType { .. } +---- + +All `Region` type-specific annotations provide additional attributes that are both common across `Region` types +as well as specific to only that type of `Region` (e.g. the `collocatedWith` and `redundantCopies` attributes +in the `PartitionRegion` annotation apply to `PARTITION` Regions only). + +More details on Apache Geode Region Types can be found +http://geode.apache.org/docs/guide/12/developing/region_options/region_types.html[here]. + +[[bootstrap-annotation-config-region-eviction]] +=== Configuring Eviction + +Managing data with Apache Geode is an active task. More than likely, tuning will be required and a combination +of features (e.g. both Eviction and <>) will need to +be employed to effectively manage your data in memory with Apache Geode. + +Given that Apache Geode is an _In-Memory Data Grid_ (IMDG), data is managed in "memory" and distributed to other nodes +that participate in a cluster in order to minimize latency, maximize throughput and ensure that data is highly available. +Since not all of an application's data is going to typically fit in memory, even across an entire cluster of nodes, +much less on a single node, capacity can be increased by adding new nodes to the cluster. This is commonly referred to +as linear scale-out (rather than scaling up, which means to add more memory, more CPU, more disk, more network bandwidth, +basically more of every system resource in order to handle the load). + +Still, even with a cluster of nodes, it is usually imperative that only the most important data be kept in memory. +Running out-of-memory, or even nearing full capacity, is rarely, if ever, a good thing. Stop-the-world GCs or worse, +`OutOfMemoryErrors`, will bring your application to a screaming halt. + +So, to help manage memory and keep the most important data around, Apache Geode supports LRU-based _Eviction_. +That is, Apache Geode evicts Region entries based on when those entries were last accessed by using +the _Least Recently Used_ algorithm. + +To enable _Eviction_, simply annotate the application class with `@EnableEviction`... + +.Spring application with Eviction enabled +[source, java] +---- +@SpringBootApplication +@PeerCacheApplication +@EnableEviction(policies = { + @EvictionPolicy(regionNames = "Books", action = EvictionActionType.INVALIDATE), + @EvictionPolicy(regionNames = { "Customers", "Orders" }, maximum = 90, + action = EvictionActionType.OVERFLOW_TO_DISK, + type = EvictonPolicyType.HEAP_PERCENTAGE) +}) +class ServerApplication { .. } +---- + +Eviction policies are usually set on the Regions in the server(s). + +As shown above, the `policies` attribute can specify 1 or more nested `@EvictionPolicy` annotations, each 1 individually +catered to 1 or more Regions where the Eviction policy needs to be applied. + +Additionally, a user can reference a custom implementation of Apache Geode's +http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/util/ObjectSizer.html[`org.apache.geode.cache.util.ObjectSizer`] interface +defined as a bean in the Spring context and referenced by name using the `objectSizerName` attribute. + +An `ObjectSizer` allows the user to define the criteria used to evaluate and determine the the size of objects stored +in the Region. + +See the `@EnableEviction` annotation _Javadoc_ for a complete list of Eviction configuration options. + +More details on Apache Geode Eviction can be found +http://geode.apache.org/docs/guide/12/developing/eviction/chapter_overview.html[here]. + +[[bootstrap-annotation-config-region-expiration]] +=== Configuring Expiration + +Along with _Eviction_, _Expiration_ can also be used to manage memory by allowing entries stored in a Region to expire. +Both _Time-to-Live_ (TTL) and _Idle-Timeout_ (TTI) based entry expiration policies are supported in Apache Geode. + +_Spring Data Geode's_ Annotation-based Expiration configuration is based on +<> that was added in +_Spring Data Geode_ many releases ago. + +Essentially, _Spring Data Geode's_ Expiration annotation support is based on a provided, custom implementation of +Apache Geode's http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/CustomExpiry.html[`org.apache.geode.cache.CustomExpiry`] interface. +This custom implementation inspects the user's application domain objects stored in a Region for the presence of +type-level Expiration annotations. + +_Spring Data Geode_ provides the following Expiration annotations used on application domain object types, +out-of-the-box... + +* `Expiration` +* `IdleTimeoutExpiration` +* `TimeToLiveExpiration` + +An application domain object type can be annotated with 1 or more of the Expiration annotations, like so... + +.Applicaton domain object specific Expiration policy +[source, java] +---- +@Region("Books") +@TimeToLiveExpiration(timeout = 30000, action = "INVALIDATE") +class Book { .. } +---- + +To enable _Expiration_, simply annotate the application class with `@EnableExpiration`... + +.Spring application with Expiration enabled +[source, java] +---- +@SpringBootApplication +@PeerCacheApplication +@EnableExpiration +class ServerApplication { .. } +---- + +In addition to application domain object type-level Expiration policies, individual Expiration policies on a +Region-by-Region basis can be configured directly with the `@EnableExpiration` annotation as well. + +.Spring application with global Expiration policies +[source, java] +---- +@SpringBootApplication +@PeerCacheApplication +@EnableExpiration(policies = { + @ExpirationPolicy(regionNames = "Books", types = ExpirationType.TIME_TO_LIVE), + @ExpirationPolicy(regionNames = { "Customers", "Orders" }, timeout = 30000, + action = ExpirationActionType.LOCAL_DESTROY) +}) +class ServerApplication { .. } +---- + +Expiration policies are usually set on the Regions in the server(s). + +See the `@EnableExpiration` annotation _Javadoc_ for a complete list of Expiration configuration options. + +More details on Apache Geode Expiration can be found +http://geode.apache.org/docs/guide/12/developing/expiration/chapter_overview.html[here]. + +[[bootstrap-annotation-config-region-off-heap]] +=== Configuring Off-Heap + +Another effective means for reducing pressure on the JVM's Heap memory and minimize GC activity is to use Apache Geode's +_Off-Heap_ memory support. Rather than storing Region entries on the JVM Heap, entries are stored in the system's +main memory. + +To enable Off-Heap support, simple annotate the application class with `@EnableOffHeap`... + +.Spring application with Off-Heap enabled +[source, java] +---- +@SpringBootApplication +@PeerCacheApplication +@EnableOffHeap(memorySize = 8192m regionNames = { "Customers", "Order" }) +class ServerApplication { .. } +---- + +The `memorySize` attribute is required. The value for the `memorySize` attribute specifies the amount of main memory +a Region is allowed to use in either megabytes (`m`) or gigabytes (`g`). + +The `regionNames` attribute is an array of Region names specifying the Regions that will store entries in main memory. +By default, all Regions will use main memory if the `regionNames` attribute is not explicitly set. + +See the `@EnableOffHeap` annotation _Javadoc_ for more details. + +[[bootstrap-annotation-config-region-indexes]] +=== Configuring Indexes + +There is not much use in storing data in Regions unless the data can be retrieved. + +In addition to `Region.get(key)` operations, particularly when the key of the value of interest is known in advance, +data is commonly retrieved by executing queries on the Regions containing the data. With Apache Geode, queries are +written using the _Object Query Language_ (OQL), and the specific data set that a client wishes to access is expressed +in the query's predicate (e.g. `SELECT * FROM /Books b WHERE b.author.name = 'Jon Doe'`). + +Generally, querying without Indexes is not very efficient. When executing queries without an Index, Apache Geode +performs the equivalent of a full table scan. + +Indexes are created and maintained for fields on objects used in query predicates to match the data of interests, +expressed by the query's projection. Different types of Indexes can be created, such as +http://geode.apache.org/docs/guide/12/developing/query_index/creating_key_indexes.html[Key] +and http://geode.apache.org/docs/guide/12/developing/query_index/creating_hash_indexes.html[Hash] Indexes. + +_Spring Data Geode_ makes it very easy to create Indexes on Regions where the data is stored and accessed. +Rather than explicitly declaring `Index` bean definitions using Spring config as before... + +.Index bean definition using Java config +[source, java] +---- +@Bean("BookIsbnIndex") +IndexFactoryBean bookIsbnIndex(GemFireCache gemfireCache) { + + IndexFactoryBean bookIsbnIndex = new IndexFactoryBean(); + + bookIsbnIndex.setCache(gemfireCache); + bookIsbnIndex.setName("BookIsbnIndex"); + bookIsbnIndex.setExpression("isbn"); + bookIsbnIndex.setFrom("/Books")); + bookIsbnIndex.setType(IndexType.KEY); + + return bookIsbnIndex; +} +---- + +Or, in <>... + +.Index bean definition using XML +[source, xml] +---- + +---- + +Indexes can now be created directly from the fields defined on application domain object types that a user knows +will be used in query predicates to speedup those queries. Indexes will be applied even for OQL queries generated +from user-defined query methods on an application's _Repository_ interfaces. + +Re-using the example `Book` class from above, we can annotate the fields on `Book` that we know will be used in queries +we define with query methods in the `BookRepository` interface... + +.Application domain object type modeling a Book using Indexes +[source, java] +---- +@Region("Books") +class Book { + + @Id + private ISBN isbn; + + @Indexed + private Author author; + + private Category category; + + private LocalDate releaseDate; + + private Publisher publisher; + + @LuceneIndexed + private String title; + +} +---- + +In our new `Book` class definition, we annotated the `author` field with `@Indexed` and the `title` field +with `@LuceneIndexed`. Also, the `isbn` field had previously been annotated with _Spring Data's_ `@Id` annotation, +which identifies the field containing the unique identifier for `Book` instances, and in _Spring Data Geode_, +the `@Id` annotated field or property is used as the key in the Region when storing the entry. + +* `@Id` annotated fields/properties result in the creation of an Apache Geode KEY Index. +* `@Indexed` annotated fields/properties result in the creation of an Apache Geode HASH Index (default). +* `@LuceneIndexed` annotated fields/properties result in the creation of an Apache Geode Lucene Index, used in +text-based searches with Apache Geode's Lucene Integration and support. + +When the `@Indexed` annotation is used without setting any attributes, the Index `name`, `expression`, and `fromClause` +are derived from the field/property of the object on which the `@Indexed` annotation has been added. The `expression` +is exactly the name of the field or property. The `fromClause` is derived from the `@Region` annotation on the object's +class (or the simple name of the domain object class if the `@Region` annotation was not specified). + +Of course, any of the `@Indexed` annotation attributes may be explicitly set to override the default values provided by +_Spring Data Geode_. + +.Application domain object type modeling a Book using cutomized Indexes +[source, java] +---- +@Region("Books") +class Book { + + @Id + private ISBN isbn; + + @Indexed(name = "BookAuthorNameIndex", expression = "author.name", type = "FUNCTIONAL") + private Author author; + + private Category category; + + private LocalDate releaseDate; + + private Publisher publisher; + + @LuceneIndexed(name = "BookTitleIndex", destory = true) + private String title; + +} +---- + +The `name` of the Index, which is auto-generated when not explicitly set, is also used as the name of the bean +registered in the Spring context for the Index. If necessary, this Index bean could even be injected by name +into another application component. + +The generated name of the Index follows the pattern: `Idx`. +For example, the name of the `author` Index would be, "`BooksAuthorHashIdx`". + +To enable Indexing, simply annotate the application class with `@EnableIndexing`... + +.Spring application with Indexing enabled +[source, java] +---- +@SpringBootApplication +@PeerCacheApplication +@EnableEntityDefinedRegions +@EnableIndexing +class ServerApplication { .. } +---- + +NOTE: The `@EnablingIndexing` annotation has no effect unless the `@EnableEntityDefinedRegions` is also declared. +Essentially, Indexes are defined from entity class types, and entity classes must be scanned in order to inspect +the entity's fields and properties for the presence of Index annotations. Without this scan, Index annotations +would not be found. It is also imperative that you limit the scope of the scan. + +While Lucene queries are not supported on _Spring Data Geode_ _Repositories_ (yet), SDG does provide comprehensive +https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/#bootstrap:lucene[support] for Apache Geode +Lucene queries using the familiar Spring _Template_ pattern. + +Finally, we close with a few extra things to keep in mind when using Indexes: + +1. While OQL Indexes are not required to execute OQL Queries, Lucene Indexes are required to execute Lucene, +text-based searches. +2. In addition, OQL Indexes are not persisted to disk; they are maintained only in memory. So, when an Apache Geode +node is restarted, the Index must be rebuilt. +3. You also need to be aware of the overhead associated in maintaining Indexes, particularly since an Index is stored +exclusively in memory, and especially when Region entries are updated. Index "maintenance" can be +http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/RegionFactory.html#setIndexMaintenanceSynchronous-boolean-[configured] +as an asynchronous task. + +Another optimization that can be utilized when re-starting your Spring application where Indexes have to be rebuilt +is to first define all the Indexes upfront and then create them all at once, which, in _Spring Data Geode_, happens +when the Spring context is refreshed. + +Indexes can be defined upfront then created all at once by setting the `define` attribute on the `@EnableIndexing` +annotation to `true`. + +See http://geode.apache.org/docs/guide/12/developing/query_index/create_multiple_indexes.html[Creating Multiple Indexes at Once] +in Apache Geode's User Guide for more details. + +Creating sensible Indexes is an important task since it is possible for an Index to do more harm than good +if not properly designed. + +See both the `@Indexed` annotation and `@LuceneIndexed` annotation _Javadoc_ for complete list of configuration options. + +More details on Apache Geode OQL Queries can be found +http://geode.apache.org/docs/guide/12/developing/querying_basics/chapter_overview.html[here]. + +More details on Apache Geode Indexes can be found +http://geode.apache.org/docs/guide/12/developing/query_index/query_index.html[here]. + +More details on Apache Geode Lucene Queries can be found +http://geode.apache.org/docs/guide/12/tools_modules/lucene_integration.html[here]. + +[[bootstrap-annotation-config-region-continuous-queries]] +=== Configuring Disk Stores + +Regions can be configured to persist data to disk. Regions can also be configured to overflow data to disk when +Region entries are evicted. In both cases, a `DiskStore` is required to persist or overflow the data. When an +explicit `DiskStore` has not been set on a Region with persistence or overflow configured, then Apache Geode will +use the "DEFAULT" `DiskStore`. + +However, it is possible and recommended to define Region-specific `DiskStores` when persisting or overflowing data +to disk. + +_Spring Data Geode_ provides Annotation support for defining and creating application Region `DiskStores` by +annotating the application class with the `@EnableDiskStore` and `@EnableDiskStores` annotations. + +TIP: `@EnableDiskStores` is a composite annotation for aggregating 1 or more `@EnableDiskStore` annotations. + +For example, while `Book` product information might mostly consist of reference data, from some external data source +(e.g. Amazon), `Order` data is most likely going to be transactional in nature and something the application is going to +need to retain, maybe even overflow to disk if the transaction volume is high enough, or so any Book publisher hopes, +anyway. + +Using the `@EnableDiskStore` annotation, I can define and create a `DiskStore` as follows... + +.Spring application defining a `DiskStore` +[source, java] +---- +@SpringBootApplication +@PeerCacheApplication +@EnableDiskStore(name = "OrdersDiskStore", autoCompact = true, compactionThreshold = 70, + maxOplogSize = 512, diskDirectories = @DiskDiretory(location = "/absolute/path/to/order/disk/files")) +class ServerApplication { .. } +---- + +Again, more than 1 `DiskStore` can be defined using the composite, `@EnableDiskStores` annotation. + +Like other Annotations in _Spring Data Geode's_ Annotation-based configuration model, both `@EnableDiskStore` +and `@EnableDiskStores` have many attributes along with associated configuration properties to apply additional +configuration to `DiskStores` created at runtime. + +Additionally, the `@EnableDiskStores` annotation defines certain common `DiskStore` attributes that apply to all +`DiskStores` created from `@EnableDiskStore` annotations composed with the `@EnableDiskStores` annotation itself. +Individual `DiskStore` configuration can override a particular global setting, but the `@EnableDiskStores` +annotation defines common configuration attributes for all `DiskStores` out of convenience. + +_Spring Data Geode_ also provides the `DiskStoreConfigurer` callback interface that can be declared in Java config +and used instead of configuration properties to customize a `DiskStore` at runtime... + +.Spring application with custom DiskStore configuration +[source, java] +---- +@SpringBootApplication +@PeerCacheApplication +@EnableDiskStore(name = "OrdersDiskStore", autoCompact = true, compactionThreshold = 70, + maxOplogSize = 512, diskDirectories = @DiskDiretory(location = "/absolute/path/to/order/disk/files")) +class ServerApplication { + + @Bean + DiskStoreConfigurer ordersDiskStoreDiretoryConfigurer( + @Value("${orders.disk.store.location}") String location) { + + return (beanName, diskStoreFactoryBean) -> { + + if ("OrdersDiskStore".equals(beanName) { + diskStoreFactoryBean.setDiskDirs(Collections.singletonList(new DiskDir(location)); + } + } + } +} +---- + +See the `@EnableDiskStore` and `@EnableDiskStores` annotation _Javadoc_ for more details on the available +attributes as well as associated configuration properties. + +More details on Apache Geode Region Persistence and Overflow (using Disk Stores) can be found +http://geode.apache.org/docs/guide/12/developing/storing_data_on_disk/chapter_overview.html[here]. + +[[bootstrap-annotation-config-continuous-queries]] +== Configuring Continuous Queries + +Another very important and useful feature of Apache Geode is +http://geode.apache.org/docs/guide/12/developing/continuous_querying/chapter_overview.html[Continuous Querying]. + +In a world of Internet-enabled things, events and streams of data are coming in from everywhere. Being able to handle +and process a large stream of data and react to events in real-time, as they happen, is becoming an increasingly +important requirement for many applications. One example is self-driving vehicles. Being able to receive, filter, +transform, analyze and act on data in real-time is a key differentiator and characteristic of real-time enabled +applications. + +Fortunately, Apache Geode was ahead of its time in this regard. Using _Continuous Queries_ (CQ) a client application +can express the data, or events it is interested in and register listeners to handle and process the events as they +arrive. The data that a client application may be interested in is expressed in a OQL query, where the query predicate +is used to filter, or identify the data of interests. When data is changed or added and it matches the criteria defined +in the query predicate of the registered CQ, the client application is notified. + +_Spring Data Geode_ makes defining and registering CQs along with an associated listener to handler and process CQ +events without all the cruft of Apache Geode's plumbing, a non-event (no pun intended). SDG's new Annotation-based +configuration for CQs builds on the already existing _Continuous Query_ support in the +<>. + +For instance, say a Book publisher wants to register interests in and receive notification anytime orders (demand) +for a `Book` exceeds the current inventory (supply), then the publisher's print application might register +the following CQ... + +.Spring `ClientCache` application with registered CQ and Listener. +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication(subcriptionEnabled = true); +@EnableContinuousQueries +class PublisherPrintApplication { + + @ContinuousQuery(name = "DemandExceedsSupply" query = + "SELECT book.* FROM /Books book, /Inventory inventory + WHERE book.title = 'How to crush it in the Book business like Amazon" + AND inventory.isbn = book.isbn + AND inventory.available < ( + SELECT sum(order.lineItems.quantity) + FROM /Orders order + WHERE order.status = 'pending' + AND order.lineItems.isbn = book.isbn + ) + ") + void handleSupplyProblem(CqEvent event) { + // start printing more Books, fast! + } +} +---- + +To enable _Continuous Queries_, simply annotate your application class with `@EnableContinuousQueries`. + +Defining _Continuous Queries_ is as simple as annotating any Spring `@Component` annotated POJO class methods +with the `@ContinuousQuery` annotation, in similar fashion to SDG's Function annotated POJO methods. A method +defined with a CQ using the `@ContinuousQuery` annotation will be called anytime data matching the query predicate +is added or changed. + +Additionally, the POJO method signature should adhere to the requirements outlined in the section on +<>. + +See the `@EnableContinuousQueries` and `@ContinuousQuery` annotation _Javadoc_ for more details on available attributes +and configuration settings. + +More details on _Spring Data Geode's_ Continuous Query support can be found +<>. + +More details on Apache Geode's Continuous Queries can be found +http://geode.apache.org/docs/guide/12/developing/continuous_querying/chapter_overview.html[here]. + +[[bootstrap-annotation-config-caching]] +== Configuring Spring's Cache Abstraction + +With _Spring Data Geode_, Apache Geode can be used as a caching provider in Spring's +https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache[Cache Abstraction]. + +In _Spring's Cache Abstraction_, the caching annotations (e.g. `@Cacheable`) identify the cache on which a cache lookup +is performed before invoking a potentially expensive operation, or where the results of an application service method +are cached after the operation is invoked. + +In _Spring Data Geode_, a Spring `Cache` corresponds directly to a Region. The Region must exist before any +`@Cacheable` application service method is called. This is true for any of Spring's caching annotations +(i.e. `@Cacheable`, `@CachePut` and `@CacheEvict`) that identify the cache to use in the operation. + +For instance, our publisher's Point-of-Sale (POS) application might have a feature to determine, or lookup +the `Price` of a `Book` during a sales transaction. + +[source, java] +---- +@Service +class PointOfSaleService + + @Cacheable("BookPrices") + Price runPriceCheckFor(Book book) { + ... + } + + @Transactional + Receipt checkout(Order order) { + ... + } + + ... +} +---- + +To make the application developer's life easier when using _Spring Data Geode_ and Apache Geode with +_Spring's Cache Abstraction_, 2 new features have been added to the **new** Annotation-based configuration model. + +Given the following Spring caching configuration... + +.Enabling Caching using Apache Geode with Spring Data Geode +[source, java] +---- +@EnableCaching +class CachingConfiguration { + + @Bean + GemfireCacheManager cacheManager(GemFireCache gemfireCache) { + + GemfireCacheManager cacheManager = new GemfireCacheManager(); + + cacheManager.setCache(gemfireCache); + + return cacheManager; + } + + @Bean("BookPricesCache") + PartitionedRegionFactoryBean bookPricesRegion(GemFireCache gemfireCache) { + + PartitionedRegionFactoryBean bookPricesRegion = + new PartitionedRegionFactoryBean<>(); + + bookPricesRegion.setCache(gemfireCache); + bookPricesRegion.setClose(false); + bookPricesRegion.setPersistent(false); + + return bookPricesRegion; + } + + @Bean("PointOfSaleService") + PointOfSaleService pointOfSaleService(..) { + return new PointOfSaleService(..); + } +} +---- + +Using _Spring Data Geode's_ new features, the same caching configuration can be simplified to... + +.Enabling GemFire Caching +[source, java] +---- +@EnableGemfireCaching +@EnableCachingDefinedRegions +class CachingConfiguration { + + @Bean("PointOfSaleService") + PointOfSaleService pointOfSaleService(..) { + return new PointOfSaleService(..); + } +} +---- + +First, the `@EnableGemfireCaching` annotation replaces both the Spring `EnableCaching` annotation along with +the need to declare an explicit `cacheManager` bean definition in the Spring config. + +Second, the `@EnableCachingDefinedRegions` annotation, like the `@EnableEntityDefinedRegions` annotation described in +<>, inspects all the Spring caching annotated application +service components to identify all the caches that will be needed by the application at runtime and creates Regions +in Apache Geode for these caches on application startup. + +The Region created is local to the application process that created the Region. If the application is a peer `Cache`, +then the Region will only exist on the application node. If the application is a `ClientCache`, then SDG creates +a client `PROXY` Region and expects that a Region with the same name already exists on the servers in the cluster. + +NOTE: SDG cannot determine the cache required by a service method using a Spring `CacheResolver` to resolve the cache +used in the operation at runtime. + +NOTE: SDG does not currently identify _JCache_, JSR-107 cache annotations used on application service components. +Refer to the core https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache-jsr-107[_Spring Framework Reference Guide_] +for the equivalent Spring caching annotation to use in place of _JCache_, JSR-107 caching annotations. + +Refer to the section, <> for more details on +using Apache Geode as a caching provider in _Spring's Cache Abstraction_. + +More details on _Spring's Cache Abstraction_ can be found +https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache[here]. + +[[bootstrap-annotation-config-cluster]] +== Configuring Cluster Configuration Push + +This may be the most exciting **new** feature in _Spring Data Geode_. + +When a client application class is annotated with `@EnableClusterConfiguration`, any Regions or Indexes defined +and declared as beans in the Spring context by the client application are "pushed" to the cluster of servers to which +the client is connected. Not only that, but this "push" is performed in such a way that Apache Geode will remember +the configuration pushed by the client. If all the nodes in the cluster go down, they will come back up with +the same configuration as before. + +In a sense, this feature is not much different than if a user were to use _Gfsh_ to create the Regions and Indexes +on all the servers in the cluster. Except now, with _Spring Data Geode_, users does **not** need to use _Gfsh_ +to create Regions and Indexes. The user's _Spring Boot_ application, enabled with the power of _Spring Data Geode_, +already contains all the configuration meta-data SDG needs to create Regions and Indexes for the user. + +When users are using the _Spring Data Repository_ abstraction, we know all the Regions (e.g. `@Region` annotated +entity types) and Indexes (e.g. `@Indexed` annotated entity fields and properties) that the users' application +will need. When users are using _Spring's Cache Abstraction_, we also know all the Regions for all the caches +identified in the caching annotations that the application is going to need. Essentially, the user is already +telling us everything we need to know just by developing her application with the entire _Spring Framework_ and all +of its provided services, infrastructure, etc, whether expressed in Annotation meta-data, Java, XML or otherwise, +and whether for configuration, for mapping, or whatever purpose. + +The user can focus on her application business logic along with using the framework provided services and +supporting infrastructure (e.g. _Spring Data Repositories_, _Spring's Transaction Management_, _Spring Caching_, etc) +and _Spring Data Geode_ will take care of all the Apache Geode plumbing required by those framework services +on the user's behalf. + +Pushing configuration from the client to the servers in the cluster and having the cluster remember it is made possible +in part by the use of Apache Geode's http://geode.apache.org/docs/guide/12/configuring/cluster_config/gfsh_persist.html[_Cluster Configuration_] +service. Apache Geode's _Cluster Configuration_ service is also the same service used by _Gfsh_ to record +schema-related changes issued by the user to the cluster from the shell. + +Of course, since the cluster "remembers" the prior configuration pushed by a client from a previous run perhaps, +_Spring Data Geode_ is careful not to stomp on any existing Regions and Indexes already defined in the servers. +This is especially important when Regions already contain data. + +NOTE: Currently there is no option to overwrite any existing Region or Index definitions. To recreate a Region +or Index, the user must use _Gfsh_ to destroy the Region or Index first and then restart the client application +so that configuration will be pushed up to the server again. Alternatively a user can just use _Gfsh_ to +(re-)define the Regions and Indexes manually. + +NOTE: Unlike _Gfsh_, _Spring Data Geode_ only supports the creation of Regions and Indexes on the servers from a client. +For advanced configuration and use cases, _Gfsh_ should be used to manage the cluster. + +For a moment, imagine the power expressed in the following configuration... + +.Spring `ClientCache` application +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableCachingDefinedRegions +@EnableEntityDefinedRegions +@EnableIndexing +@EnableGemfireCaching +@EnableGemfireRepositories +@EnableClusterConfiguration +class ClientApplication { .. } +---- + +An application developer instantly gets a _Spring Boot_, Apache Geode `ClientCache` application using +_Spring Data Repositories_ with _Spring's Cache Abstraction_, using Apache Geode as the caching provider, +where Regions and Indexes are not only created on the client, but pushed to the servers in the cluster. + +All the application developer need do is define the application's domain model objects annotated with mapping +and Index annotations, define Repository interfaces supporting basic data access operations and querying +for each of the entity types, define the service components containing the business logic manipulating +the entities, declare the appropriate annotations on service methods that require caching, transactional +behavior, etc, and the developer is in business. Nothing the user did in this case pertains to infrastructure +and plumbing required in the application's back-end services (e.g. Apache Geode). Database users have similar +features, no Spring, Apache Geode developers can too. + +When combined with a couple more _Spring Data Geode_ Annotations... + +* `@EnableContinuousQueries` +* `@EnableGemfireFunctionExecutions` +* `@EnableGemfireCacheTransactions` + +Then, the application is really going to start to take flight. + +See the `@EnableClusterConfiguration` annotation _Javadoc_ for more details. + +[[bootstrap-annotation-config-security]] +== Configuring Security + +Without a doubt, application _Security_ is extremely important and _Spring Data Geode_ provides comprehensive support +for securing both Apache Geode clients and servers. + +Recently, Apache Geode introduced a new http://geode.apache.org/docs/guide/12/managing/security/implementing_security.html[Integrated Security] framework, +replacing its old Authentication and Authorization Security model, for handling authentication and authorization. +One of the main features and benefits of this new Security framework is that it integrates with +https://shiro.apache.org/[Apache Shiro] and can therefore delegate both authentication and authorization requests +to Apache Shiro when enforcing security. + +The following demonstrates how _Spring Data Geode_ can simplify Apache Geode's Security story even further. + +[[bootstrap-annotation-config-security-server]] +=== Configuring Server Security + +There are several different ways in which a user can configure Security for servers in an Apache Geode cluster. + +1. Implement the Apache Geode `org.apache.geode.security.SecurityManager` interface and set Apache Geode's +`security-manager` property to refer to your application `SecurityManager` implementation by the FQCN. +Alternatively, users can construct and initialize an instance of their `SecurityManager` implementation and set it +with http://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/CacheFactory.html#setSecurityManager-org.apache.geode.security.SecurityManager-[CacheFactory.setSecurityManager(:SecurityManager)] +method when creating an instance of an Apache Geode peer `Cache`. + +2. Create an Apache Shiro https://shiro.apache.org/configuration.html[`shiro.ini`] file with the _users_, _roles_ +and _permissions_ defined for your application, then set the Apache Geode `security-shiro-init` property to refer +to this `shiro.ini` file, which must be available in the `CLASSPATH`. + +3. Using just Apache Shiro, annotate your _Spring Boot_ application class with _Spring Data Geode's_ **new** +`@EnableSecurity` annotation and define 1 or more Apache Shiro https://shiro.apache.org/realm.html[`Realms`] (as needed) +as beans in the Spring context for accessing your application's Security meta-data (i.e. _authorized users_, _roles_ +and _permissions_), and your done! + +The problem with the first approach is that a user must implement his/her own `SecurityManager`, which can be quite +tedious and error prone. Implementing a custom `SecurityManager` does afford a user some flexibility in accessing +Security meta-data from whatever data source stores the meta-data, such as LDAP or even a proprietary, internal +data source, but then that is a problem already solved by configuring and using Apache Shiro `Realms`, which is more +universally known and non-Apache Geode specific. + +TIP: See Apache Geode's Security examples for http://geode.apache.org/docs/guide/12/managing/security/authentication_examples.html[Authentication] +and http://geode.apache.org/docs/guide/12/managing/security/authorization_example.html[Authorization] as 1 possible way +to implement your own custom, application specific `SecurityManager`. + +The second approach using an Apache Shiro INI file is marginally better, but a user still needs to be familiar with +the INI file format in the first place. Additionally, an INI file is static and not easily updatable at runtime. + +The third approach is the most ideal since it adheres to widely known and industry accepted concepts +(i.e. Apache Shiro's Security framework) and is easy to setup... + +.Spring server application using Apache Shiro +[source, java] +---- +@SpringBootApplication +@CacheServerApplication +@EnableSecurity +class ServerApplication { + + @Bean + PropertiesRealm shiroRealm() { + PropertiesRealm propertiesRealm = new PropertiesRealm(); + propertiesRealm.setResourcePath("classpath:shiro.properties"); + propertiesRealm.setPermissionResolver(new GeodePermissionResolver()); + return propertiesRealm; + } +} +---- + +NOTE: The configured `Realm` shown in the example above could have easily been any of Apache Shiro's supported +`Realms` out-of-the-box (https://shiro.apache.org/static/1.3.2/apidocs/org/apache/shiro/realm/activedirectory/package-frame.html[ActiveDirectory], +https://shiro.apache.org/static/1.3.2/apidocs/org/apache/shiro/realm/jdbc/package-frame.html[JDBC], +https://shiro.apache.org/static/1.3.2/apidocs/org/apache/shiro/realm/jndi/package-frame.html[JNDI], +https://shiro.apache.org/static/1.3.2/apidocs/org/apache/shiro/realm/ldap/package-frame.html[LDAP], +or even a `Realm` supporting the https://shiro.apache.org/static/1.3.2/apidocs/org/apache/shiro/realm/text/IniRealm.html[INI format]) +or even a custom implementation of an Apache Shiro `Realm` implemented by the user. See Apache Shiro's +https://shiro.apache.org/realm.html[documentation on Realms] +for more details. + +When Apache Shiro is on the `CLASSPATH` of the servers in the cluster and 1 or more Apache Shiro `Realms` have been +defined as beans in the Spring context, _Spring Data Geode_ will detect this configuration and use Apache Shiro +as the Security provider to secure your Apache Geode servers when the `@EnableSecurity` annotation is used. + +TIP: Earlier, information was posted on _Spring Data Geode's_ support for Apache Geode's **new** Integrated Security +framework using Apache Shiro in this +https://spring.io/blog/2016/11/10/spring-data-geode-1-0-0-incubating-release-released[spring.io blob post]. + +See the `@EnableSecurity` annotation _Javadoc_ for more details on available attributes and associated +configuration properties. + +More details on Apache Geode Security can be found +http://geode.apache.org/docs/guide/12/managing/security/chapter_overview.html[here]. + +[[bootstrap-annotation-config-security-client]] +=== Configuring Client Security + +The Security story would not be complete without discussing how to secure Spring-based, Apache Geode cache client +applications. + +Apache Geode's process to securing a client application is, well, rather involved. In a nutshell, a user essentially +needs to... + +1. Provide an implementation of the +http://geode.apache.org/releases/latest/javadoc/org/apache/geode/security/AuthInitialize.html[`org.apache.geode.security.AuthInitialize`] interface. +2. Set the Apache Geode `security-client-auth-init` (System) property to refer to the custom, application-provided +`AuthInitialize` interface. +3. And finally, a user would typically specify the user credentials in a proprietary, Apache Geode +`gfsecurity.properties` file. + +_Spring Data Geode_ simplifies all of that using the same `@EnableSecurity` annotation as applied to +server applications. In other words, the same `@EnableSecurity` annotation handles Security for both client +and server applications. This makes it easier for users when they decide to switch their applications from +an embedded peer `Cache` application to a `ClientCache` application, for instance. Simply change the SDG annotation +from `@PeerCacheApplication` or `@CacheServerApplication` to `@ClientCacheApplication` and you are done. + +Effectively, all a user need do on the client is... + +.Spring client application using `@EnableSecurity` +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableSecurity +class ClientApplication { .. } +---- + +Then define the familiar _Spring Boot_ `application.properties` file containing the required _username_ and _password_ +Security properties and you are all set. + +.Spring Boot `application.properties` file with the required Security credentials +[source, java] +---- +spring.data.gemfire.security.username=jackBlack +spring.data.gemfire.security.password=b@cK!nB1@cK +---- + +That was easy! + +TIP: By default, _Spring Boot_ can find an `application.properties` file when placed in the root of +the application's `CLASSPATH`. Of course, Spring supports may ways to to locate resources using its +https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#resources[Resource abstraction]. + +See the `@EnableSecurity` annotation _Javadoc_ for more details on available attributes and associated +configuration properties. + +More details on Apache Geode Security can be found +http://geode.apache.org/docs/guide/12/managing/security/chapter_overview.html[here]. + +[[bootstrap-annotation-config-tips]] +== Configuration Tips + +The following tips will help users get the most out of using the **new** Annotation-based configuration model. + +[[bootstrap-annotation-config-tips-organization]] +== Configuration Organization + +As we saw in the section on <>, when +many Apache Geode and/or _Spring Data Geode_ features are enabled using Annotations, we start to stack a lot of +Annotations on the Spring `@Configuration` or `@SpringBootApplication` class. In this situation, it makes sense +to start compartmentalizing the configuration a bit. + +For instance, given... + +.Spring `ClientCache` application with the kitcken sink to boot +[source, java] +---- +@SpringBootApplication +@ClientCacheApplication +@EnableContinuousQueries +@EnableCachingDefinedRegions +@EnableEntityDefinedRegions +@EnableIndexing +@EnableGemfireCaching +@EnableGemfireFunctionExecutions +@EnableGemfireRepositories +@EnableGemfireCacheTransactions +@EnableClusterConfiguration +class ClientApplication { .. } +---- + +We could break this configuration down by concern. For example... + +.Spring `ClientCache` application with the kitcken sink to boot +[source, java] +---- +@SpringBootApplication +@Import({ CachingConfiguration.class, GeodeConfiguration.class, + QueriesAndFunctionsConfiguration.class, RepositoryConfiguration.class }) +class ClientApplication { .. } + +@EnableGemfireCaching +@EnableCachingDefinedRegions +class CachingConfiguration { .. } + +@ClientCacheApplication +@EnableClusterConfiguration +@EnableGemfireCacheTransactions +class GeodeConfiguration { .. } + +@EnableContinuousQueries +@EnableGemfireFunctionExecutions +class QueriesAndFunctionsConfiguration { + + @ContinuousQuery(..) + void processCqEvent(CqEvent event) { + ... + } +} + +@EnableGemfireRepositories +@EnableEntityDefinedRegions +@EnableIndexing +class RepositoryConfiguration { .. } +---- + +Spring does not care. Organize your application configuration as you see fit. + +[[bootstrap-annotation-config-tips-undocumented-annotations]] +== Additional Configuration-based Annotations + +_SDG Annotations you never heard of..._ + +The following SDG Annotations were not discussed in this reference documentation either because the Annotation supports +a deprecated feature of Apache Geode, or there are better, alternative ways to accomplishing the function that +the Annotation provides. + +* `@EnableAuth` - enable Apache Geode's old Authentication/Authorization Security model. (_Deprecated_; +use Apache Geode's new _Integrated Security_ framework discussed <>). +* `@EnableAutoRegionLookup` - Not recommended. Essentially, this Annotation supports finding Regions defined in +external configuration meta-data (e.g. `cache.xml`, or _Cluster Configuration_ when applied to a server) and registers +those Regions as beans in the Spring context automatically. Users should generally prefer Spring config when +using Spring and _Spring Data Geode_. See <> +and <> instead. +* `@EnableBeanFactoryLocator` - enables the SDG `GemfireBeanFactoryLocator` feature, which is only useful, again, when +using external configuration meta-data (e.g. `cache.xml`). For example, if a user defines a `CacheLoader` on a +Region defined in `cache.xml`, the user can still auto-wire this `CacheLoader` with say, a relational database +`DataSource` bean defined in Spring confif. This Annotation takes advantage of this SDG <> +and might be useful for users who have a large amount of legacy configuration meta-data, like `cache.xml` files. +* `@EnableGemFireAsLastResource` - is actually discussed in +<> with Apache Geode. +* `@EnableMcast` - enables Apache Geode's old peer discovery mechanism using UDP-based Multi-cast Networking. +(_Deprecated_; users should be using Apache Geode Locators instead; see +<>. +* `@EnableRegionDataAccessTracing` - is useful for debugging purposes; the Annotation enables tracing for all +data access operations performed on a Region by registering an AOP Aspect that proxies all Regions declared +as beans in the Spring context, intercepting the Region op and logging the event. + +[[bootstrap-annotation-config-conclusion]] +== Conclusion + +As we learned in the previous sections, there is a tremendous amount of power provided by _Spring Data Geode_'s +**new** Annotation-based configuration model. Hopefully, it lives up to its goal of making it easier for users +to get started quickly when using Apache Geode with Spring. + +Keep in mind when using the new Annotations that it does not preclude you, the application developer, from using +Java config, or even XML, if you prefer. You can even combine all 3 approaches by using Spring's +https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Import.html[`@Import`] +and https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/ImportResource.html[`@ImportResource`] +annotations on a Spring `@Configuration` or `@SpringBootApplication` class, if you like. The moment you explicitly +provide a bean definition that would otherwise be provided by _Spring Data Geode_ using an Annotation, +the Annotation-based configuration backs away. + +In certain cases you may even need to fallback to Java config, as in the `Configurers` case, to handle more complex +or conditional configuration logic that is not easily expressed in or cannot be accomplished using Annotations. +Do not be alarmed; this is to be expected. + +For example, another case where Java config or XML will be needed is when configuring Apache Geode WAN components, +which currently do not have any Annotation configuration support. However, defining and registering WAN components +is as simple as using the `org.springframework.data.gemfire.wan.GatewaReceiverFactoryBean` +and `org.springframework.data.gemfire.wan.GatewaySenderFactoryBean` API classes in Java configuration on your Spring +`@Configuration` or `@SpringBootApplication` classes (recommended). + +The Annotations were not meant to handle every situation; the Annotations were meant to help application developers +**get up and running** as **quickly** and as **easily** as possible, especially during development. diff --git a/src/main/asciidoc/reference/data.adoc b/src/main/asciidoc/reference/data.adoc index 61f31125..6b0f229a 100644 --- a/src/main/asciidoc/reference/data.adoc +++ b/src/main/asciidoc/reference/data.adoc @@ -510,7 +510,7 @@ These aspects can easily be configured and changed through the _Spring_ containe the `DBLoader` code. [[apis:spring-cache-abstraction]] -== Support for Spring Cache Abstraction +== Support for the Spring Cache Abstraction _Spring Data Geode_ provides an implementation of the _Spring_ http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#cache[Cache Abstraction]