[[bootstrap-annotation-config]]
= Bootstrapping Pivotal GemFire using Spring Annotations

_Spring Data for Pivotal GemFire_ (SDG) 2.0 introduces a **new** Annotation-based configuration model
to configure and bootstrap Pivotal GemFire using the Spring container.

The primary motivation for introducing an Annotation-based approach to the configuration of Pivotal GemFire 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

Pivotal GemFire can be very difficult to setup and use correctly given all the
http://gemfire.docs.pivotal.io/geode/reference/topics/gemfire_properties.html[configuration properties],
configuration options:
(http://gemfire-93-javadocs.docs.pivotal.io/)[Java API],
(http://gemfire.docs.pivotal.io/geode/reference/topics/chapter_overview_cache_xml.html[cache.xml],
http://gemfire.docs.pivotal.io/gemfire/tools_modules/gfsh/chapter_overview.html[_Gfsh_]
with http://gemfire.docs.pivotal.io/geode/configuring/chapter_overview.html[_Cluster Configuration_],
<<bootstrap,Spring XML/Java-based configuration>>)
in addition to different supported _topologies_
(http://gemfire.docs.pivotal.io/geode/topologies_and_comm/cs_configuration/chapter_overview.html[client/server],
http://gemfire.docs.pivotal.io/geode/topologies_and_comm/p2p_configuration/chapter_overview.html[P2P],
http://gemfire.docs.pivotal.io/geode/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 for Pivotal GemFire'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 <<bootstrap, Bootstrapping
Pivotal GemFire with the Spring Container>> for more details.

NOTE: As of SDG 2.0, the new Annotation-based configuration model does not yet have configuration support
for Pivotal GemFire's WAN components and topology.

Like _Spring Boot_, _Spring Data for Pivotal GemFire's_ Annotation-based configuration model was designed as an opinionated,
_convention over configuration_ approach for using Pivotal GemFire.  Indeed, this 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 configuration attributes
out-of-the-box. The default value for a given Annotation attribute directly corresponds to the default value
provided in Pivotal GemFire for the same configuration property or setting.

The intention is to let an application developer enable a Pivotal GemFire feature or an embedded service by simply
declaring the Annotation on his/her Spring `@Configuration` or `@SpringBootApplication` 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 Pivotal GemFire is there should an application
developer need it and _Spring Data for Pivotal GemFire'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 Pivotal GemFire 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 Pivotal GemFire 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 Pivotal GemFire cache application simply by declaring
1 of 3 main Annotations:

1. `@ClientCacheApplication`
2. `@PeerCacheApplication`
3. `@CacheServerApplication`

These 3 Annotations are the Spring/Pivotal GemFire 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 Pivotal GemFire: a _client_ or a _peer_.

A _Spring Boot_ application can be configured as an Pivotal GemFire cache client (i.e. with an instance of `ClientCache`),
which communicates with an existing, standalone cluster of Pivotal GemFire servers used to manage the application's data.
The _client/server_ topology is the most typical system architecture employed when using Pivotal GemFire 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 Pivotal GemFire cluster.  That is, the application
itself is just another server in the cluster of servers that will manage data.  The _Spring Boot_ 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` serving cache clients, allowing clients to connect
and perform data access operations on the server.  This is accomplished by annotating the application class with
`@CacheServerApplication` instead of `@PeerCacheApplication`, which will create a peer `Cache` instance along with
the `CacheServer`.

NOTE: An Pivotal GemFire Server is not necessarily a "_Cache Server_" by default.  That is, a server is not necessarily
setup to serve cache clients just because it is a "server".  A Pivotal GemFire Server can just be a peer member/data node
of the cluster that manages data without serving any clients while other peer members in the cluster are indeed setup
to serve  clients in addition to managing data.  It also possible to setup certain peer members as non-data node,
http://gemfire.docs.pivotal.io/geode/developing/region_options/data_hosts_and_accessors.html[data accessors]
that can service clients as `CacheServers` as well, but is beyond the scope of this document.

By way of example, if I wanted to create a _Spring Boot_, Pivotal GemFire cache client application, I would start with...

.Spring-based Pivotal GemFire `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 Pivotal GemFire, then I would start with...

.Spring-based Pivotal GemFire embedded peer `Cache` application
[source, java]
----
@SpringBootApplication
@PeerCacheApplication
class ServerApplication { .. }
----

Alternatively, a user may use the `@CacheServerApplication` annotation instead of `@PeerCacheApplication` to create
both an "embedded" peer `Cache` instance along with a `CacheServer` running on "_localhost_", listening on
the default cache server port, *40404*...

.Spring-based Pivotal GemFire 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 an Pivotal GemFire cluster.
The most common and recommended approach is to use Pivotal GemFire Locators.

NOTE: A cache client can connect to 1 or more Locators in the Pivotal GemFire 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 contain
the data of interests to the client, or which servers have the least amount of load.  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, to obtain the data requested.

NOTE: Locators are also peer members in a cluster.  Locators actually constitute what makes up a cluster of Pivotal GemFire
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 Pivotal GemFire sets up a "DEFAULT" `Pool` connected to a `CacheServer` running on "_localhost_", listening on port
**40404** by default when a `ClientCache` instance is created, and a `CacheServer` listens on port **40404** accepting
connections on all system NICs, there is nothing special a user needs to 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 ready to go.

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 for Pivotal GemFire_ approach, with Annotations.

As an application developer, you will no doubt want to customize the "DEFAULT" `Pool` setup by Pivotal GemFire
to possibly connect to 1 or more Locators, for instance...

.Spring-based Pivotal GemFire `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,
if necessary.

NOTE: You can only use either the `locators` or `servers` attribute, but not both, which is enforced by Pivotal GemFire.

A user may also configure additional `Pools`, other than the "DEFAULT" `Pool` provided by Pivotal GemFire 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 Pivotal GemFire `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 Pivotal GemFire.

Similarly, on the server, a user can configure multiple `CacheServers` that a client can connect to...

.Spring-based Pivotal GemFire `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.  Again, Java 8 and earlier does not allow more than 1 annotation of the same type
to be declared on a 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 the configuration 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_ and/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 to be `Strings` thereby giving up _Type-Safety_; not acceptable!

So, _Spring Data for Pivotal GemFire_ 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`].

The `Configurers` design pattern are a way to allow application developers to receive a callback to customize
the configuration of a component, or bean 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 for Pivotal GemFire_ provides several `Configurer` callback interfaces to customize different aspects of Annotation-based
configuration meta-data at runtime, before the _Spring_ 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 _Spring Boot_ `CacheServer` and `ClientCache` applications, respectively.

First, in our server application...

.Customizing a Spring Boot `CacheServer` application with a `CacheServerConfigurer`
[source, java]
----
@SpringBootApplication
@CacheServerApplication(name = "SpringServerApplication", logLevel = "info")
class ServerApplication {

  @Bean
  CacheServerConfigurer cacheServerPortConfigurer(
          @Value("${gemfire.cache.server.host:localhost}") String cacheServerHost
          @Value("${gemfire.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("${gemfire.cache.server.host:localhost}") String cacheServerHost
          @Value("${gemfire.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 at runtime, during startup.

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_ using the `@Value` annotation
on factory method parameters, and so on.

All _Spring Data for Pivotal GemFire_-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
create and configure the Pivotal GemFire component (e.g. a `ClientCache` instance is created and configured 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.  So, in essence, the Annotations are a facade
and provide an extra layer of abstraction for convenience.

Given a `Configurer` can be declared as a regular bean definition like any other POJO, it is not difficult to imagine
a user combining different Spring configuration options, such as the use of _Spring Profiles_ with `Conditions`
using both Property Placeholders and SpEL expressions  as well as other nifty 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 a
_Spring Boot_ `application.properties` file.

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.pool.Venus.servers=venus[48484]
spring.data.gemfire.pool.Venus.max-connections=200
spring.data.gemfire.pool.Venus.min-connections=50
spring.data.gemfire.pool.Venus.ping-interval=15000
spring.data.gemfire.pool.Venus.pr-single-hop-enabled=true
spring.data.gemfire.pool.Venus.read-timeout=20000
spring.data.gemfire.pool.Venus.subscription-enabled=true
spring.data.gemfire.pool.Saturn.locators=skullbox[20668]
spring.data.gemfire.pool.Saturn.subscription-enabled=true
spring.data.gemfire.pool.Neptune.servers=saturn[41414],neptune[42424]
spring.data.gemfire.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 = "Venus"),
    @EnablePool(name = "Saturn"),
    @EnablePool(name = "Neptune")
})
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 Annotation-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=${gemfire.cache.server.port:40404}
----

Or, in Java...

[source, java]
----
  @Bean
  CacheServerConfigurer cacheServerPortConfigurer(
          @Value("${gemfire.cache.server.port:${some.other.property:40404}}") int cacheServerPort) {

      ...
  }
}
----

Property placeholder nesting can be arbitrarily deep.

[[bootstrap-annotation-config-embedded-services]]
== Configuring embedded services

Pivotal GemFire 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, Pivotal GemFire 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 for Pivotal GemFire_
applications to startup up a small cluster of 2 or 3 Pivotal GemFire servers.  Rather than starting a separate Locator
process, a user can simply annotate her _Spring Boot_ `@CacheServerApplication` class with `@EnableLocator`.

.Spring, Pivotal GemFire `CacheServer` application running an embedded Locator
[source, java]
----
@SpringBootApplication
@CacheServerApplication
@EnableLocator
class ServerApplication { .. }
----

The `@EnableLocator` annotation starts an embedded Locator in the Spring, Pivotal GemFire `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.

Additionally, the `@EnableLocator` attributes may be set with the `spring.data.gemfire.locator.host`
and `spring.data.gemfire.locator.port` properties in `application.properties` as well.

Then, it is possible to start other _Spring Boot_, `@CacheServerApplication` enabled applications connecting to this
Locator with...

.Spring, Pivotal GemFire `CacheServer` application connecting to a Locator
[source, java]
----
@SpringBootApplication
@CacheServerApplication(locators = "localhost[10334]")
class ServerApplication { .. }
----

You can even combine both application classes shown above into a single class and use your IDE to create different
run profile configurations to 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.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 Pivotal GemFire Servers running on your local system.  Pretty slick!

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 strongly recommended that Locators be stand-alone,
independent processes in the cluster.

More details on how Pivotal GemFire Locators work can be found
http://gemfire.docs.pivotal.io/geode/topologies_and_comm/topology_concepts/how_member_discovery_works.html[here].

[[bootstrap-annotation-config-embedded-services-manager]]
=== Configuring an embedded Manager

An Pivotal GemFire 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 along with monitoring the runtime
operations and behavior of these components.

The Manager allows a JMX-enabled client (e.g. the _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 `@Configuration` or `@SpringBootApplication` class with `@EnableManager` and you are in business.

By default, the Manager binds to "_localhost_" listening on the default Pivotal GemFire 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 Pivotal GemFire

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)<ec><v0>:1024
SpringCacheServerTwo   | 10.99.199.5(SpringCacheServerTwo:14844)<v1>:1025
SpringCacheServerThree | 10.99.199.5(SpringCacheServerThree:14846)<v2>:1026
----

Because we also have the embedded Locator enabled, we are able to connect indirectly to the Manager through
the Locator.  A Locator allows JMX clients to connect and find a Manager node in the cluster.  If none exist,
the Locator will assume the role of a Manager.  However, if no existing Locator is present, 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 annotation and not something an application developer should use in production.  It is strongly recommended
that Managers, like Locators, be stand-alone, independent and dedicated processes in the cluster.

More details on Pivotal GemFire Management and Monitoring can be found
http://gemfire.docs.pivotal.io/gemfire/managing/book_intro.html[here].

[[bootstrap-annotation-config-embedded-services-http]]
=== Configuring the embedded HTTP Server

Pivotal GemFire 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 Pivotal GemFire's Management (Admin) REST API (not a publicly advertised API),
the http://gemfire.docs.pivotal.io/geode/rest_apps/book_intro.html[Developer REST API]
and the http://gemfire.docs.pivotal.io/geode/tools_modules/pulse/pulse-overview.html[Pulse Monitoring Web Application].

However, to use any of these Pivotal GemFire provided Web applications, you must have a full installation of Pivotal GemFire
installed on your system, and you must set the `GEODE_HOME` 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 and the services provided.

[[bootstrap-annotation-config-embedded-services-memcached]]
=== Configuring the embedded Memcached Server (Gemcached)

Pivotal GemFire also implements the Memcached protocol with the ability to service Memcached clients.  That is Memcached
clients can connect to an Pivotal GemFire cluster and perform Memcached operations as if the Pivotal GemFire 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 Pivotal GemFire's _Gemcached_ service can be found
http://gemfire.docs.pivotal.io/geode/tools_modules/gemcached/chapter_overview.html[here].

[[bootstrap-annotation-config-embedded-services-redis]]
=== Configuring the embedded Redis Server

Pivotal GemFire also implements the Redis Server protocol, which enables Redis clients to connect to and communicate with
a cluster of Pivotal GemFire Servers to issue Redis commands.  As of this writing, the Redis Server protocol support
in Pivotal GemFire 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 Pivotal GemFire's Redis Adapter can be found
http://gemfire.docs.pivotal.io/geode/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 Pivotal GemFire 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.

Additionally, you can specify the `log-level` using the `spring.data.gemfire.logging.level` property
in `application.properties`.

See the `@EnableLogging` annotation _Javadoc_ for more details.

[[bootstrap-annotation-config-statistics]]
== Configuring Statistics

To gain even deeper insight into Pivotal GemFire at 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 where timing is a crucial factor.

When _Statistics_ are enabled, a user can use Pivotal GemFire'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 Pivotal GemFire'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 Pivotal GemFire is
http://gemfire.docs.pivotal.io/geode/developing/data_serialization/gemfire_pdx_serialization.html[PDX Serialization].
While a complete discussion on PDX is 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 existing applications
using either older or newer versions of the PDX serialized, application domain objects that have changed,
and 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 Pivotal GemFire 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.

Enabling PDX serialization is much simpler than modifying all of your application domain object types to be
`java.io.Serializable`, which maybe undesirable to impose such restrictions on your application domain model.

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://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxSerializable.html[`org.apache.geode.pdx.PdxSerializable`]
interface, or an application developer will choose to implement and register a non-invasive implementation of the
http://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/pdx/PdxSerializer.html[`org.apache.geode.pdx.PdxSerializer`]
interface to handle all the application domain object types that need to be serialized.

Unfortunately, Pivotal GemFire 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 unmaintainable practice to be sure.

Even though only a single `PdxSerializer` instance can be registered with Pivotal GemFire , it makes sense to create a
single `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 all of the 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 for Pivotal GemFire_ will take care of registering it with Pivotal GemFire 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 Pivotal GemFire's
http://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/pdx/ReflectionBasedAutoSerializer.html[`org.apache.geode.pdx.ReflectionBasedAutoSerializer`]
as a bean definition in a Spring context.  Alternatively, you should use _Spring Data for Pivotal GemFire'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 or properties (e.g. keystores, usernames/passwords, etc)...

.Spring `ClientCache` application with SSL enabled
[source, java]
----
@SpringBootApplication
@ClientCacheApplication
@EnableSsl
public class ClientApplication { .. }
----

Different Pivotal GemFire components: `GATEWAY`, `HTTP`, `JMX`, `LOCATOR`, `SERVER` can be individually configured
with SSL, or they can all be collectively configured at once to use SSL using the `CLUSTER` enumerated value.

It is easy to specify which Pivotal GemFire components that the SSL configuration settings should applied to using
the nested `@EnableSsl` annotation `Component` enum...

.Spring `ClientCache` application with SSL enabled by Aache Pivotal GemFire 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 Pivotal GemFire SSL support can be found
http://gemfire.docs.pivotal.io/geode/managing/security/ssl_overview.html[here].

[[bootstrap-annotation-config-gemfire-properties]]
== Configuring Pivotal GemFire Properties

While many of the http://gemfire.docs.pivotal.io/geode/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 _Pivotal GemFire Properties_ are still accessible from the `@EnablePivotal GemFireProperties` annotation.

Using the `@EnablePivotal GemFireProperties` annotation on your application class is convenient and a nice alternative to
creating a `gemfire.properties` file or setting _Pivotal GemFire Properties_ as Java System properties on the command-line
when launching your application.

TIP: It is recommended that these _Pivotal GemFire 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 testing purposes.

A few examples of some of the less common _Pivotal GemFire 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 _Pivotal GemFire Property_, simply annotate your application class with `@EnablePivotal GemFireProperties`
and set the _Pivotal GemFire Properties_ you want to change from the default, out-of-the-box value set by Pivotal GemFire...

.Spring `ClientCache` application with specific _Pivotal GemFire Properties_ set
[source, java]
----
@SpringBootApplication
@ClientCacheApplication
@EnablePivotal GemFireProperties(conflateEvents = true, socketBufferSize = 16384)
public class ClientApplication { .. }
----

Keep in mind, some of the _Pivotal GemFire Properties_ are client specific (e.g. `conflateEvents`) while others are
server specific (e.g. `distributedSystemId`, `enableNetworkPartitionDetection`, `enforceUniqueHost`, `memberTimeout`,
`redundancyZone`, etc).

More details on Pivotal GemFire properties can be found
http://gemfire.docs.pivotal.io/geode/reference/topics/gemfire_properties.html[here].

[[bootstrap-annotation-config-regions]]
== Configuring Regions

So far, outside of PDX, our discussion has centered around configuring Pivotal GemFire'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.

Pivotal GemFire organizes data in a cache into
http://gemfire.docs.pivotal.io/geode/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` and writing queries.  We will talk about Indexing
<<bootstrap-annotation-config-indexes,later>>.

Previously, _Spring Data for Pivotal GemFire_ 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 Pivotal GemFireConfiguration {

  @Bean("Example")
  PartitionedRegionFactoryBean exampleRegion(Pivotal GemFireCache gemfireCache) {

      PartitionedRegionFactoryBean<Long, Example> exampleRegion =
          new PartitionedRegionFactoryBean<>();

      exampleRegion.setCache(gemfireCache);
      exampleRegion.setClose(false);
      exampleRegion.setPersistent(true);

      return exampleRegion;
  }

  ...
}
----

Or, using <<bootstrap:region, XML>>...

.Example Region bean definition using the SDG XML Namespace
[source, xml]
----
  <gfe:partitioned-region id="exampleRegion" name="Example" persistent="true">
     ...
  </gfe:partitioned-region>
----

While neither Java nor XML configuration is all that difficult 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 hundreds or even thousands of tables.

Ugh!

Now users can define and configure Regions based on their application domain objects (i.e. entities).  No longer will
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 for Pivotal GemFire_ combines the use of _Spring Data_ _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 for Pivotal GemFire's_  <<gemfire-repositories,implementation/extension>> of _Spring Data's_ _Repository abstraction_,
which has been specifically customized to optimize data access operations for Pivotal GemFire.

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, an 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<Book, ISBN> { .. }
----

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<BooK> findByAuthor(Author author);`).

Under-the-hood, _Spring Data for Pivotal GemFire_ provides an implementation of the applications _Repository_ 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 <<gemfire-repositories.executing-queries,conventions>>.

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 for Pivotal GemFire_ 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 for Pivotal GemFire_ 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
@EnableEntityDefinedRegions(basePackages = "example.app.domain")
@EnableGemfireRepositories(basePackages = "example.app.repo")
class ClientApplication { .. }
----

TIP: Creating Regions from entity classes is the most useful when using _Spring Data Repositories_ in your application.
_Spring Data for Pivotal GemFire's_ _Repository_ support is enabled with the `@EnableGemfireRepositories` annotation, as shown
in the example above.

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 declared.

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

Pivotal GemFire supports many different
http://gemfire.docs.pivotal.io/geode/developing/region_options/region_types.html[types of Regions].
Each type corresponds to the Region's
http://gemfire-91-javadocs.docs.pivotal.io/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://gemfire.docs.pivotal.io/geode/developing/region_options/storage_distribution_options.html[Storage and Distribution Options]
in the Pivotal GemFire User Guide for more details.

When the user annotates her application domain object types with the generic `@Region` mapping annotation,
_Spring Data for Pivotal GemFire_ 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 for Pivotal GemFire_, 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 with an embedded peer `Cache`.

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 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: Region-level Idle-Timeout (TTI) and Time-To-Live (TTL) expiration policies are independent of and different from
entry-level 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 simply declare 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 Pivotal GemFire Region Types can be found
http://gemfire.docs.pivotal.io/geode/developing/region_options/region_types.html[here].

[[bootstrap-annotation-config-region-eviction]]
=== Configuring Eviction

Managing data with Pivotal GemFire is an active task.  More than likely, tuning will be required and a combination
of features (e.g. both _Eviction_ and <<bootstrap-annotation-config-region-expiration, _Expiration_>>) will need to
be employed to effectively manage your data in memory with Pivotal GemFire.

Given that Pivotal GemFire 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 venturing near 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, Pivotal GemFire supports LRU-based _Eviction_.
That is, Pivotal GemFire 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 Pivotal GemFire's
http://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/cache/util/ObjectSizer.html[`org.apache.geode.cache.util.ObjectSizer`] interface,
which can be 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 a Region.

See the `@EnableEviction` annotation _Javadoc_ for a complete list of Eviction configuration options.

More details on Pivotal GemFire Eviction can be found
http://gemfire.docs.pivotal.io/geode/developing/eviction/chapter_overview.html[here].

[[bootstrap-annotation-config-region-expiration]]
=== Configuring Expiration

Along with <<bootstrap-annotation-config-region-eviction, _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 Pivotal GemFire.

_Spring Data for Pivotal GemFire's_ Annotation-based Expiration configuration is based on
<<bootstrap:region:expiration:annotation, earlier and existing entry expiration annotation support>>  added in
_Spring Data for Pivotal GemFire_ version 1.5.

Essentially, _Spring Data for Pivotal GemFire's_ Expiration annotation support is based on a provided, custom implementation of
Pivotal GemFire's http://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/cache/CustomExpiry.html[`org.apache.geode.cache.CustomExpiry`] interface.
This `o.a.g.cache.CustomExpiry` implementation inspects the user's application domain objects stored in a Region
for the presence of type-level Expiration annotations.

_Spring Data for Pivotal GemFire_ 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 Pivotal GemFire Expiration can be found
http://gemfire.docs.pivotal.io/geode/developing/expiration/chapter_overview.html[here].

[[bootstrap-annotation-config-region-compression]]
=== Configuring Compression

In addition to <<bootstrap-annotation-config-region-expiration,_Eviction_>>
and <<bootstrap-annotation-config-region-expiration,_Expiration_>>, a user may also configure his or her data Regions
to use Compression in order to reduce memory consumption.

Pivotal GemFire allows users to compress in-memory Region values using pluggable
http://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/compression/Compressor.html[`Compressors`],
or different compression codecs.  Out-of-the-box, Pivotal GemFire uses Google's http://google.github.io/snappy/[Snappy]
compression library.

To enable Compression support, simply annotate the application class with `@EnableCompression`...

.Spring application with Compression enabled
[source, java]
----
@SpringBootApplication
@ClientCacheApplication
@EnableCompression(compressorBeanName = "MyCompressor", regionNames = { "Customers", "Orders" })
class ClientApplication { .. }
----

NOTE: Neither the `compressorBeanName` nor the `regionNames` attribute are required.

The `compressorBeanName` defaults to "`SnappyCompressor`" enabling Pivotal GemFire's provided
http://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/compression/SnappyCompressor.html[`SnappyCompressor`]
by default.

The `regionNames` attribute is an array of Region names specifying the Regions that will have compression enabled.
By default, all Regions will compress values if the `regionNames` attribute is not explicitly set.

TIP: Alternatively, a user may use the `spring.data.gemfire.cache.compression.compressor-bean-name`
and `spring.data.gemfire.cache.compression.region-names` properties in the `application.properties` file
to set and configure the values of these `@EnableCompression` annotation attributes.

WARNING: To use Pivotal GemFire's Region Compression feature, you must include the `org.iq80.snappy:snappy` dependency
in your application _Maven_ `pom.xml` file, or `build.gradle` file when using _Gradle_.  This is only necessary
if you use Pivotal GemFire's default, out-of-the-box support for Region Compression, which uses the
http://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/compression/SnappyCompressor.html[`SnappyCompressor`]
by default.  Of course, if you are using another compression library, you will need to include dependencies
for that compression library on your application's classpath.  Additionally, you will need to implement Pivotal GemFire's
http://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/compression/Compressor.html[`Compressor`] interface
to adapt your compression library of choice, define it as a bean in the _Spring_ context, and then set
the `compressorBeanName` to this custom bean definition.

See the `@EnableCompression` annotation _Javadoc_ for more details.

More details on Pivotal GemFire Compression can be found
http://gemfire91.docs.pivotal.io/geode/managing/region_compression.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
Pivotal GemFire's _Off-Heap_ memory support.  Rather than storing Region entries on the JVM Heap, entries are stored
in the system's main memory.  Off-Heap generally works best when the objects being stored are uniform in size,
are mostly less than 128K and do not need to be deserialized frequently, as explained in the Pivotal GemFire
http://gemfire.docs.pivotal.io/geode/managing/heap_use/off_heap_management.html[User Guide].

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", "Orders" })
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.

TIP: Alternatively, a user may use the `spring.data.gemfire.cache.off-heap.memory-size`
and `spring.data.gemfire.cache.off-heap.region-names` properties in the `application.properties` file
to set and configure the values of these `@EnableOffHeap` annotation attributes.

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 accessed.

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 Pivotal GemFire, 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, Pivotal GemFire
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://gemfire.docs.pivotal.io/geode/developing/query_index/creating_key_indexes.html[Key]
and http://gemfire.docs.pivotal.io/geode/developing/query_index/creating_hash_indexes.html[Hash] Indexes.

_Spring Data for Pivotal GemFire_ 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("BooksIsbnIndex")
IndexFactoryBean bookIsbnIndex(Pivotal 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 <<bootstrap:indexing, XML>>...

.Index bean definition using XML
[source, xml]
----
  <gfe:index id="BooksIsbnIndex" expression="isbn" from="/Books" type="KEY"/>
----

Indexes can now be defined directly on the fields declared in application domain object types that a user knows
will be used in query predicates to speedup those queries.  Indexes will even be applied 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 for Pivotal GemFire_,
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 Pivotal GemFire KEY Index.
* `@Indexed` annotated fields/properties result in the creation of an Pivotal GemFire HASH Index (default).
* `@LuceneIndexed` annotated fields/properties result in the creation of an Pivotal GemFire Lucene Index, used in
text-based searches with Pivotal GemFire'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 class 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 domain 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 for Pivotal GemFire_.

.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: `<Region Name><Field/Property Name><Index Type>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 fields/properties on the 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 strongly recommended that you limit the scope of the scan.

While Lucene queries are not supported on _Spring Data for Pivotal GemFire_ _Repositories_ (yet), SDG does provide comprehensive
https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/#bootstrap:lucene[support] for Pivotal GemFire
Lucene queries using the familiar Spring _Template_ design pattern.

Finally, we close with a few extra tips 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 Pivotal GemFire
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://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/cache/RegionFactory.html#setIndexMaintenanceSynchronous-boolean-[configured]
as an asynchronous task.

Another optimization that may 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 for Pivotal GemFire_, 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://gemfire.docs.pivotal.io/geode/developing/query_index/create_multiple_indexes.html[Creating Multiple Indexes at Once]
in Pivotal GemFire'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 Pivotal GemFire OQL Queries can be found
http://gemfire.docs.pivotal.io/geode/developing/querying_basics/chapter_overview.html[here].

More details on Pivotal GemFire Indexes can be found
http://gemfire.docs.pivotal.io/geode/developing/query_index/query_index.html[here].

More details on Pivotal GemFire Lucene Queries can be found
http://gemfire.docs.pivotal.io/geode/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 Pivotal GemFire
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 for Pivotal GemFire_ 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
and author 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 for Pivotal GemFire's_ Annotation-based configuration model, both `@EnableDiskStore`
and `@EnableDiskStores` have many attributes along with associated configuration properties to customize
the `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 will override a particular global setting, but the `@EnableDiskStores`
annotation conveniently defines common configuration attributes applied across all `DiskStores` aggregated by
the annotation.

_Spring Data for Pivotal GemFire_ also provides the `DiskStoreConfigurer` callback interface, which 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 Pivotal GemFire Region Persistence and Overflow (using Disk Stores) can be found
http://gemfire.docs.pivotal.io/geode/developing/storing_data_on_disk/chapter_overview.html[here].

[[bootstrap-annotation-config-continuous-queries]]
== Configuring Continuous Queries

Another very important and useful feature of Pivotal GemFire is
http://gemfire.docs.pivotal.io/geode/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, Pivotal GemFire 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
occur.  The data that a client application may be interested in is expressed as an 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 for Pivotal GemFire_ makes defining and registering CQs along with an associated listener to handle and process CQ
events without all the cruft of Pivotal GemFire's plumbing, a non-event (no pun intended).  SDG's new Annotation-based
configuration for CQs builds on the existing _Continuous Query_ support in the
<<apis:continuous-query, _Continuous Query Listener Container_>>.

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 POJO 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
<<apis:continuous-query:adapter, ContinuousQueryListener and ContinuousQueryListenerAdapter>>.

See the `@EnableContinuousQueries` and `@ContinuousQuery` annotation _Javadoc_ for more details on
available attributes and configuration settings.

More details on _Spring Data for Pivotal GemFire's_ Continuous Query support can be found
<<apis:continuous-query, here>>.

More details on Pivotal GemFire's Continuous Queries can be found
http://gemfire.docs.pivotal.io/geode/developing/continuous_querying/chapter_overview.html[here].

[[bootstrap-annotation-config-caching]]
== Configuring Spring's Cache Abstraction

With _Spring Data for Pivotal GemFire_, Pivotal GemFire 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 for Pivotal GemFire_, a Spring `Cache` corresponds directly to a Region.  The Region must exist before any
`@Cacheable` application service methods are 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 for Pivotal GemFire_ and Pivotal GemFire 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 Pivotal GemFire with Spring Data for Pivotal GemFire
[source, java]
----
@EnableCaching
class CachingConfiguration {

  @Bean
  GemfireCacheManager cacheManager(Pivotal GemFireCache gemfireCache) {

      GemfireCacheManager cacheManager = new GemfireCacheManager();

      cacheManager.setCache(gemfireCache);

      return cacheManager;
  }

  @Bean("BookPricesCache")
  ReplicatedRegionFactoryBean<Book, Price> bookPricesRegion(Pivotal GemFireCache gemfireCache) {

    ReplicatedRegionFactoryBean<Book, Price> bookPricesRegion =
        new ReplicatedRegionFactoryBean<>();

    bookPricesRegion.setCache(gemfireCache);
    bookPricesRegion.setClose(false);
    bookPricesRegion.setPersistent(false);

    return bookPricesRegion;
  }

  @Bean("PointOfSaleService")
  PointOfSaleService pointOfSaleService(..) {
      return new PointOfSaleService(..);
  }
}
----

Using _Spring Data for Pivotal GemFire's_ new features, the same caching configuration can be simplified to...

.Enabling Pivotal 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
<<bootstrap-annotation-config-regions, Configuring Regions>>, inspects all the Spring application, caching annotated
service components to identify all the caches that will be needed by the application at runtime and creates Regions
in Pivotal GemFire 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.

TIP: SDG also supports _JCache_, JSR-107 cache annotations on application service components as well.
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, <<apis:spring-cache-abstraction, Support for the Spring Cache Abstraction>> for more details on
using Pivotal GemFire 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 for Pivotal GemFire_.

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 Pivotal GemFire will
remember the configuration pushed by the client, when using HTTP.  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, manually.  Except now, with _Spring Data for Pivotal GemFire_, 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 for Pivotal GemFire_, already contains all the configuration meta-data needed 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 needed by the application's service components.  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 point is, users can focus on their application business logic along with using the framework provided services
and supporting infrastructure (e.g. _Spring Data Repositories_, _Spring's Transaction Management_, _Spring Caching_,
and so on) and _Spring Data for Pivotal GemFire_ will take care of all the Pivotal GemFire 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 Pivotal GemFire's http://gemfire.docs.pivotal.io/geode/configuring/cluster_config/gfsh_persist.html[_Cluster Configuration_]
service.  Pivotal GemFire's _Cluster Configuration_ service is also the same service used by _Gfsh_ to record
schema-related changes (e.g. `gfsh> create region --name=Example --type=PARTITION`) 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 for Pivotal GemFire_ 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, for instance.

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 for Pivotal GemFire_ 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, just 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_, Pivotal GemFire `ClientCache` application using
_Spring Data Repositories_ with _Spring's Cache Abstraction_, using Pivotal GemFire 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 simple queryies
for each of the entity types, define the service components containing the business logic transacting
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. Pivotal GemFire).  Database users have similar
features.  Now Spring, Pivotal GemFire developers can too!

When combined with a couple more _Spring Data for Pivotal GemFire_ Annotations...

* `@EnableContinuousQueries`
* `@EnableGemfireFunctionExecutions`
* `@EnableGemfireCacheTransactions`

Then, this application is really going to start to take flight, with very minimal effort.

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 for Pivotal GemFire_ provides comprehensive support
for securing both Pivotal GemFire clients and servers.

Recently, Pivotal GemFire introduced a new http://gemfire.docs.pivotal.io/geode/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 for Pivotal GemFire_ can simplify Pivotal GemFire'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 Pivotal GemFire cluster.

1. Implement the Pivotal GemFire `org.apache.geode.security.SecurityManager` interface and set Pivotal GemFire'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://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/cache/CacheFactory.html#setSecurityManager-org.apache.geode.security.SecurityManager-[CacheFactory.setSecurityManager(:SecurityManager)]
method when creating an instance of an Pivotal GemFire 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 Pivotal GemFire `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 for Pivotal GemFire'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-Pivotal GemFire specific.

TIP: See Pivotal GemFire's Security examples for http://gemfire.docs.pivotal.io/geode/managing/security/authentication_examples.html[Authentication]
and http://gemfire.docs.pivotal.io/geode/managing/security/authorization_example.html[Authorization]  as 1 possible way
to implement your own custom, application specific `SecurityManager`.  However, this is strongly **not** recommended.

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 Pivotal GemFirePermissionResolver());

      return propertiesRealm;
  }
}
----

TIP: 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 perhaps 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 for Pivotal GemFire_ will detect this configuration and use Apache Shiro
as the Security provider to secure your Pivotal GemFire servers when the `@EnableSecurity` annotation is used.

TIP: Earlier, information was posted on _Spring Data for Pivotal GemFire's_ support for Pivotal GemFire'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 Pivotal GemFire Security can be found
http://gemfire.docs.pivotal.io/geode/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, Pivotal GemFire cache client
applications.

Pivotal GemFire'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://gemfire-91-javadocs.docs.pivotal.io/org/apache/geode/security/AuthInitialize.html[`org.apache.geode.security.AuthInitialize`] interface.
2. Set the Pivotal GemFire `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, Pivotal GemFire
`gfsecurity.properties` file.

_Spring Data for Pivotal GemFire_ 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 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 Pivotal GemFire Security can be found
http://gemfire.docs.pivotal.io/geode/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 <<bootstrap-annotation-config-cluster, _Configuring Cluster Configuration Push_>>, when
many Pivotal GemFire and/or _Spring Data for Pivotal GemFire_ 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
@EnableGemfireCacheTransactions
@EnableGemfireCaching
@EnableGemfireFunctionExecutions
@EnableGemfireRepositories
@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({ Pivotal GemFireConfiguration.class, CachingConfiguration.class,
    FunctionsConfiguration.class, QueriesConfiguration.class,
    RepositoriesConfiguration.class })
class ClientApplication { .. }

@ClientCacheApplication
@EnableClusterConfiguration
@EnableGemfireCacheTransactions
class Pivotal GemFireConfiguration { .. }

@EnableGemfireCaching
@EnableCachingDefinedRegions
class CachingConfiguration { .. }

@EnableGemfireFunctionExecutions
class FunctionsConfiguration { .. }

@EnableContinuousQueries
class QueriesConfiguration {

   @ContinuousQuery(..)
   void processCqEvent(CqEvent event) {
       ...
   }
}

@EnableEntityDefinedRegions
@EnableGemfireRepositories
@EnableIndexing
class RepositoriesConfiguration { .. }
----

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 Pivotal GemFire, or there are better, alternative ways to accomplishing the function that
the Annotation provides.

* `@EnableAuth` - enable Pivotal GemFire's old Authentication/Authorization Security model.  (_Deprecated_;
use Pivotal GemFire's new _Integrated Security_ framework discussed <<bootstrap-annotation-config-security, here>>).
Again, Pivotal GemFire's new _Integrated Security_ framework can be enabled on both clients and servers using SDG's
`@EnableSecurity` annotation as described in <<bootstrap-annotation-config-security, Configuring Security>>.
* `@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 for Pivotal GemFire_.  See <<bootstrap-annotation-config-regions, Configuring Regions>>
and <<bootstrap-annotation-config-cluster, Configuring Cluster Configuration Push>> 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 config.  This Annotation takes advantage of this SDG <<apis:declarable, feature>>
and might be useful for users who have a large amount of legacy configuration meta-data, like `cache.xml` files.
* `@EnablePivotal GemFireAsLastResource` - is actually discussed in
<<apis:global-transaction-management, Global - JTA Transaction Management>> with Pivotal GemFire.
* `@EnableMcast` - enables Pivotal GemFire's old peer discovery mechanism using UDP-based Multi-cast Networking.
(_Deprecated_; users should be using Pivotal GemFire Locators instead; see
<<bootstrap-annotation-config-embedded-services-locator, Configuring Locators>>.
* `@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 for Pivotal GemFire_'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 Pivotal GemFire 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 for Pivotal GemFire_ 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 Pivotal GemFire 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.GatewayReceiverFactoryBean`
and `org.springframework.data.gemfire.wan.GatewaySenderFactoryBean` API classes in Java configuration of 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.

We hope you will enjoy these new capabilities!
