[[geode-clientcache-applications]]
== Building `ClientCache` Applications
:geode-name: {apache-geode-name}


The first opinionated option provided to you by Spring Boot for {geode-name} (SBDG) out-of-the-box is a
{apache-geode-javadoc}/org/apache/geode/cache/client/ClientCache.html[ClientCache] instance simply by declaring
Spring Boot for {geode-name} on your application classpath.

It is assumed that most application developers using Spring Boot to build applications backed by {geode-name} will be
building cache client applications deployed in an {geode-name}
{apache-geode-docs}/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology].
The _client/server topology_ is the most common and traditional architecture employed by enterprise applications when
using {geode-name}.

For example, you can begin building a Spring Boot, {geode-name} `ClientCache` application by declaring the
`spring-geode-starter` on your application's classpath:

.Spring Boot for {geode-name} on the application classpath
[source,xml]
----
<dependency>
  <groupId>org.springframework.geode</groupId>
  <artifactId>spring-geode-starter</artifactId>
</dependency>
----

Then, you configure and bootstrap your Spring Boot, {geode-name} `ClientCache` application with the following
main application class:

.Spring Boot, {geode-name} `ClientCache` Application
[source,java]
----
@SpringBootApplication
public class SpringBootApacheGeodeClientCacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApacheGeodeClientCacheApplication.class, args);
    }
}
----

Your application now has a `ClientCache` instance, which is able to connect to an {geode-name} server running on
`localhost`, listening on the default `CacheServer` port, `40404`.

By default, an {geode-name} server (i.e. `CacheServer`) must be running in order to use the `ClientCache` instance.
However, it is perfectly valid to create a `ClientCache` instance and perform data access operations using `LOCAL`
Regions. This is very useful during development.

TIP: To develop with `LOCAL` Regions, you only need to configure your cache Regions with the
{apache-geode-javadoc}/org/apache/geode/cache/client/ClientRegionShortcut.html#LOCAL[`ClientRegionShortcut.LOCAL`]
data management policy.

When you are ready to switch from your local development environment (IDE) to a client/server architecture in a managed
environment, you simply change the data management policy of the client Region from `LOCAL` back to the default `PROXY`,
or even a `CACHING_PROXY`, which will cause the data to be sent/received to and from 1 or more servers, respectively.

TIP: Compare and contrast the above configuration with Spring Data for {geode-name}
{spring-data-geode-docs-html}/#bootstrap-annotation-config-geode-applications[approach].

It is uncommon to ever need a direct reference to the `ClientCache` instance provided by SBDG injected into your
application components (e.g. `@Service` or `@Repository` beans defined in a Spring `ApplicationContext`) whether you
are configuring additional {geode-name} objects (e.g. Regions, Indexes, etc) or simply using those objects indirectly
in your applications. However, it is also possible to do so if and when needed.

For example, perhaps you want to perform some additional `ClientCache` initialization in a Spring Boot
{spring-boot-javadoc}/org/springframework/boot/ApplicationRunner.html[ApplicationRunner] on startup:

.Injecting a `GemFireCache` reference
[source,java]
----
@SpringBootApplication
public class SpringBootApacheGeodeClientCacheApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApacheGeodeClientCacheApplication.class, args);
    }

    @Bean
    ApplicationRunner runAdditionalClientCacheInitialization(GemFireCache gemfireCache) {

        return args -> {

            ClientCache clientCache = (ClientCache) gemfireCache;

            // perform additional ClientCache initialization as needed
        };
    }
}
----

[[geode-peercache-applications]]
=== Building Embedded (Peer & Server) Cache Applications

What if you want to build an embedded, peer `Cache` application instead?

Perhaps you need an actual peer cache member, configured and bootstrapped with Spring Boot, along with the ability
to join this member to an existing cluster (of data servers) as a peer node.  Well, you can do that too.

Remember the 2nd goal in Spring Boot's {spring-boot-docs-html}/#getting-started-introducing-spring-boot[documentation]:

> _Be opinionated out of the box but get out of the way quickly as requirements start to diverge from the defaults._

It is the 2nd part, "_get out of the way quickly as requirements start to diverge from the defaults_"
that we refer to here.

If your application requirements demand you use Spring Boot to configure and bootstrap an embedded, peer `Cache`
instance, then simply declare your intention with either SDG's
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/PeerCacheApplication.html[`@PeerCacheApplication`] annotation,
or alternatively, if you need to enable connections from `ClientCache` apps as well, use SDG's
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/CacheServerApplication.html[`@CacheServerApplication`] annotation:

.Spring Boot, {geode-name} `CacheServer` Application
[source,java]
----
@SpringBootApplication
@CacheServerApplication(name = "SpringBootApacheGeodeCacheServerApplication")
public class SpringBootApacheGeodeCacheServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApacheGeodeCacheServerApplication.class, args);
    }
}
----

TIP: An {geode-name} "server" is not necessarily a `CacheServer` capable of serving cache clients. It is merely a peer
member node in an {geode-name} cluster (a.k.a. distributed system) that stores and manages data.

By explicitly declaring the `@CacheServerApplication` annotation, you are telling Spring Boot that you do not want
the default, `ClientCache` instance, but rather an embedded, peer `Cache` instance with a `CacheServer` component,
which enables connections from `ClientCache` apps.

You can also enable 2 other {geode-name} services, an embedded _Locator_, which allows clients or even other peers
to "locate" servers in the cluster, as well as an embedded _Manager_, which allows the {geode-name} application process
to be managed and monitored using {apache-geode-docs}/tools_modules/gfsh/chapter_overview.html[_Gfsh_], {geode-name}'s
command-line shell tool:

.Spring Boot, {geode-name} `CacheServer` Application with _Locator_ and _Manager_ services enabled
[source,java]
----
@SpringBootApplication
@CacheServerApplication(name = "SpringBootApacheGeodeCacheServerApplication")
@EnableLocator
@EnableManager
public class SpringBootApacheGeodeCacheServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApacheGeodeCacheServerApplication.class, args);
    }
}
----

Then, you can use _Gfsh_  to connect to and manage this server:

[source,text]
----
$ echo $GEMFIRE
/Users/jblum/pivdev/apache-geode-1.2.1

$ gfsh
    _________________________     __
   / _____/ ______/ ______/ /____/ /
  / /  __/ /___  /_____  / _____  /
 / /__/ / ____/  _____/ / /    / /
/______/_/      /______/_/    /_/    1.2.1

Monitor and Manage Apache Geode

gfsh>connect
Connecting to Locator at [host=localhost, port=10334] ..
Connecting to Manager at [host=10.0.0.121, port=1099] ..
Successfully connected to: [host=10.0.0.121, port=1099]


gfsh>list members
                   Name                     | Id
------------------------------------------- | --------------------------------------------------------------------------
SpringBootApacheGeodeCacheServerApplication | 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:29798)<ec><v0>:1024

gfsh>
gfsh>describe member --name=SpringBootApacheGeodeCacheServerApplication
Name        : SpringBootApacheGeodeCacheServerApplication
Id          : 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:29798)<ec><v0>:1024
Host        : 10.0.0.121
Regions     :
PID         : 29798
Groups      :
Used Heap   : 168M
Max Heap    : 3641M
Working Dir : /Users/jblum/pivdev/spring-boot-data-geode/spring-geode-docs/build
Log file    : /Users/jblum/pivdev/spring-boot-data-geode/spring-geode-docs/build
Locators    : localhost[10334]

Cache Server Information
Server Bind              :
Server Port              : 40404
Running                  : true
Client Connections       : 0
----

You can even start additional servers in _Gfsh_, which will connect to your Spring Boot configured and bootstrapped
{geode-name} `CacheServer` application. These additional servers started in _Gfsh_ know about the Spring Boot,
{geode-name} server because of the embedded _Locator_ service, which is running on `localhost`, listening on
the default _Locator_ port, `10334`:

[source,text]
----
gfsh>start server --name=GfshServer --log-level=config --disable-default-server
Starting a Geode Server in /Users/jblum/pivdev/lab/GfshServer...
...
Server in /Users/jblum/pivdev/lab/GfshServer on 10.0.0.121 as GfshServer is currently online.
Process ID: 30031
Uptime: 3 seconds
Geode Version: 1.2.1
Java Version: 1.8.0_152
Log File: /Users/jblum/pivdev/lab/GfshServer/GfshServer.log
JVM Arguments: -Dgemfire.default.locators=10.0.0.121:127.0.0.1[10334] -Dgemfire.use-cluster-configuration=true -Dgemfire.start-dev-rest-api=false -Dgemfire.log-level=config -XX:OnOutOfMemoryError=kill -KILL %p -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/jblum/pivdev/apache-geode-1.2.1/lib/geode-core-1.2.1.jar:/Users/jblum/pivdev/apache-geode-1.2.1/lib/geode-dependencies.jar


gfsh>list members
                   Name                     | Id
------------------------------------------- | --------------------------------------------------------------------------
SpringBootApacheGeodeCacheServerApplication | 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:29798)<ec><v0>:1024
GfshServer                                  | 10.0.0.121(GfshServer:30031)<v1>:1025
----

Perhaps you want to start the other way around.  As developer, I may need to connect my Spring Boot configured
and bootstrapped {geode-name} server application to an existing cluster. You can start the cluster in _Gfsh_
by executing the following commands:

[source,text]
----
gfsh>start locator --name=GfshLocator --port=11235 --log-level=config
Starting a Geode Locator in /Users/jblum/pivdev/lab/GfshLocator...
...
Locator in /Users/jblum/pivdev/lab/GfshLocator on 10.0.0.121[11235] as GfshLocator is currently online.
Process ID: 30245
Uptime: 3 seconds
Geode Version: 1.2.1
Java Version: 1.8.0_152
Log File: /Users/jblum/pivdev/lab/GfshLocator/GfshLocator.log
JVM Arguments: -Dgemfire.log-level=config -Dgemfire.enable-cluster-configuration=true -Dgemfire.load-cluster-configuration-from-dir=false -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/jblum/pivdev/apache-geode-1.2.1/lib/geode-core-1.2.1.jar:/Users/jblum/pivdev/apache-geode-1.2.1/lib/geode-dependencies.jar

Successfully connected to: JMX Manager [host=10.0.0.121, port=1099]

Cluster configuration service is up and running.


gfsh>start server --name=GfshServer --log-level=config --disable-default-server
Starting a Geode Server in /Users/jblum/pivdev/lab/GfshServer...
....
Server in /Users/jblum/pivdev/lab/GfshServer on 10.0.0.121 as GfshServer is currently online.
Process ID: 30270
Uptime: 4 seconds
Geode Version: 1.2.1
Java Version: 1.8.0_152
Log File: /Users/jblum/pivdev/lab/GfshServer/GfshServer.log
JVM Arguments: -Dgemfire.default.locators=10.0.0.121[11235] -Dgemfire.use-cluster-configuration=true -Dgemfire.start-dev-rest-api=false -Dgemfire.log-level=config -XX:OnOutOfMemoryError=kill -KILL %p -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/jblum/pivdev/apache-geode-1.2.1/lib/geode-core-1.2.1.jar:/Users/jblum/pivdev/apache-geode-1.2.1/lib/geode-dependencies.jar


gfsh>list members
   Name     | Id
----------- | --------------------------------------------------
GfshLocator | 10.0.0.121(GfshLocator:30245:locator)<ec><v0>:1024
GfshServer  | 10.0.0.121(GfshServer:30270)<v1>:1025
----

Then, modify the `SpringBootApacheGeodeCacheServerApplication` class to connect to the existing cluster, like so:

.Spring Boot, {geode-name} `CacheServer` Application connecting to an external cluster
[source,java]
----
@SpringBootApplication
@CacheServerApplication(name = "SpringBootApacheGeodeCacheServerApplication", locators = "localhost[11235]")
public class SpringBootApacheGeodeCacheServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootApacheGeodeClientCacheApplication.class, args);
    }
}
----

TIP: Notice I configured the `SpringBootApacheGeodeCacheServerApplication` class, `@CacheServerApplication` annotation's
`locators` property with the host and port (i.e. "_localhost[11235]_") on which I started my _Locator_ using _Gfsh_.

After running your Spring Boot, {geode-name} `CacheServer` application again, and then running `list members` in _Gfsh_,
you should see:

[source,text]
----
gfsh>list members
                   Name                     | Id
------------------------------------------- | ----------------------------------------------------------------------
GfshLocator                                 | 10.0.0.121(GfshLocator:30245:locator)<ec><v0>:1024
GfshServer                                  | 10.0.0.121(GfshServer:30270)<v1>:1025
SpringBootApacheGeodeCacheServerApplication | 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:30279)<v2>:1026


gfsh>describe member --name=SpringBootApacheGeodeCacheServerApplication
Name        : SpringBootApacheGeodeCacheServerApplication
Id          : 10.0.0.121(SpringBootApacheGeodeCacheServerApplication:30279)<v2>:1026
Host        : 10.0.0.121
Regions     :
PID         : 30279
Groups      :
Used Heap   : 165M
Max Heap    : 3641M
Working Dir : /Users/jblum/pivdev/spring-boot-data-geode/spring-geode-docs/build
Log file    : /Users/jblum/pivdev/spring-boot-data-geode/spring-geode-docs/build
Locators    : localhost[11235]

Cache Server Information
Server Bind              :
Server Port              : 40404
Running                  : true
Client Connections       : 0
----

In both scenarios, the Spring Boot configured and bootstrapped {geode-name} server and the _Gfsh_ _Locator_
and _Gfsh_ _Server_ formed a cluster.

While you can use either approach and Spring does not care, it is far more convenient to use Spring Boot and your IDE
to form a small cluster while developing.  By leveraging Spring profiles, it is far simpler and much faster to
configure and start a small cluster.

Plus, this is useful for rapidly prototyping, testing and debugging your entire, end-to-end application
and system architecture, all right from the comfort and familiarity of your IDE of choice.  No additional tooling
(e.g. _Gfsh_) or knowledge is required to get started quickly and easily.

Just _build_ and _run_!

TIP: Be careful to vary your port numbers for the embedded services, like the `CacheServer`, _Locators_ and _Manager_,
especially if you start multiple instances, otherwise you will run into a `java.net.BindException`
due to port conflicts.

TIP: See the Appendix, <<geode-cluster-configuration-bootstrapping>> for more details.

[[geode-locator-applications]]
=== Building Locator Applications

In addition to `ClientCache`, `CacheServer` and peer `Cache` applications, SDG, and by extension SBDG, now supports
Locator-based, Spring Boot applications.

An {geode-name} Locator is a location-based service, or alternatively and more typically, a standalone process enabling
clients to "locate" a cluster of {geode-name} servers to manage data. Many cache clients can connect to the same cluster
in order to share data. Running multiple clients is common in a Microservices architecture where you need to scale-up
the number of app instances to satisfy the demand.

A Locator is also used by joining members of an existing cluster to scale-out and increase capacity of the logically
pooled system resources (i.e. Memory, CPU and Disk).  A Locator maintains metadata that is sent to the clients to
enable capabilities like single-hop data access, routing data access operations to the data node in the cluster
maintaining the data of interests.  A Locator also maintains load information for servers in the cluster, which enables
the load to be uniformly distributed across the cluster while also providing fail-over services to a redundant member
if the primary fails. A Locator provides many more benefits and you are encouraged to read
the {apache-geode-docs}/configuring/running/running_the_locator.html[documentation] for more details.

As shown above, a Locator service can be embedded within either a peer `Cache` or `CacheServer`, Spring Boot application
using the SDG `@EnableLocator` annotation:

.Embedded Locator Service
[source,java]
----
@SpringBootApplication
@CacheServerApplication
@EnableLocator
class SpringBootCacheServerWithEmbeddedLocatorApplication {
	// ...
}
----

However, it is more common to start standalone Locator JVM processes.  This is useful when you want to increase
the resiliency of your cluster in face of network and process failures, which are bound to happen.  If a Locator JVM
process crashes or gets severed from the cluster due to a network failure, then having multiple Locators provides a
higher degree of availability (HA) through redundancy.

Not to worry though, if all Locators in the cluster go down, then the cluster will still remain intact.
You simply won't be able to add more peer members (i.e. scale-up the number of data nodes in the cluster)
or connect any more clients.  If all the Locators in the cluster go down, then it is safe to simply restart them
only after a thorough diagnosis.

NOTE: Once a client receives metadata about the cluster of servers, then all data access operations are sent directly
to servers in the cluster, not a Locator.  Therefore, existing, connected clients will remain connected and operable.

To configure and bootstrap Locator-based, Spring Boot applications as standalone JVM processes, use the following
configuration:

.Standalone Locator Process
[source,java]
----
@SpringBootApplication
@LocatorApplication
class SpringBootApacheGeodeLocatorApplication {
	// ...
}
----

Instead of using the `@EnableLocator` annotation, you now use the `@LocatorApplication` annotation.

The `@LocatorApplication` annotation works in the same way as the `@PeerCacheApplication` and `@CacheServerApplication`
annotations, bootstrapping an {geode-name} process, overriding the default `ClientCache` instance provided by SBDG
out-of-the-box.

NOTE: If your `@SpringBootApplication` class is annotated with `@LocatorApplication`, then it can only be a `Locator`
and not a `ClientCache`, `CacheServer` or peer `Cache` application.  If you need the application to function as a
peer `Cache`, perhaps with an embedded `CacheServer` components and embedded Locator, then you need to follow
the approach shown above using the `@EnableLocator` annotation with either the `@PeerCacheApplication`
or `@CacheServerApplication` annotation.

With our Spring Boot, {geode-name} Locator application, we can connect both Spring Boot configured and bootstrapped
peer members (peer `Cache`, `CacheServer` and `Locator` applications) as well as _Gfsh_ started Locators and Servers.

First, let's startup 2 Locators using our {geode-name} Locator, Spring Boot application class.

.SpringBootApacheGeodeLocatorApplication class
[source,java]
----
include::{docs-src-dir}/org/springframework/geode/docs/example/app/locator/SpringBootApacheGeodeLocatorApplication.java[tags=class]
----

We also need to vary the configuration for each Locator app instance.

{geode-name} requires each peer member in the cluster to be uniquely named. We can set the name of the Locator by using
the `spring.data.gemfire.locator.name` SDG property set as a JVM System Property in your IDE's Run Configuration Profile
for the application main class like so: `-Dspring.data.gemfire.locator.name=SpringLocatorOne`. We name the second
Locator app instance, "_SpringLocatorTwo_".

Additionally, we must vary the port numbers that the Locators use to listen for connections. By default, an {geode-name}
Locator listens on port `10334`.  We can set the Locator port using the `spring.data.gemfire.locator.port` SDG property.

For our first Locator app instance (i.e. "_SpringLocatorOne_"), we also enable the "_manager_" Profile so that
we can connect to the Locator using _Gfsh_.

Our IDE Run Configuration Profile for our first Locator app instance appears as:

`-server -ea -Dspring.profiles.active=manager -Dspring.data.gemfire.locator.name=SpringLocatorOne -Dlogback.log.level=INFO`

And our IDE Run Configuration Profile for our second Locator app instance appears as:

`-server -ea -Dspring.profiles.active= -Dspring.data.gemfire.locator.name=SpringLocatorTwo -Dspring.data.gemfire.locator.port=11235 -Dlogback.log.level=INFO`

You should see log output similar to the following when you start a Locator app instance:

.Spring Boot, {geode-name} Locator log output
[source,txt]
----
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::  (v2.2.0.BUILD-SNAPSHOT)

2019-09-01 11:02:48,707  INFO .SpringBootApacheGeodeLocatorApplication:  55 - Starting SpringBootApacheGeodeLocatorApplication on jblum-mbpro-2.local with PID 30077 (/Users/jblum/pivdev/spring-boot-data-geode/spring-geode-docs/out/production/classes started by jblum in /Users/jblum/pivdev/spring-boot-data-geode/spring-geode-docs/build)
2019-09-01 11:02:48,711  INFO .SpringBootApacheGeodeLocatorApplication: 651 - No active profile set, falling back to default profiles: default
2019-09-01 11:02:49,374  INFO xt.annotation.ConfigurationClassEnhancer: 355 - @Bean method LocatorApplicationConfiguration.exclusiveLocatorApplicationBeanFactoryPostProcessor is non-static and returns an object assignable to Spring's BeanFactoryPostProcessor interface. This will result in a failure to process annotations such as @Autowired, @Resource and @PostConstruct within the method's declaring @Configuration class. Add the 'static' modifier to this method to avoid these container lifecycle issues; see @Bean javadoc for complete details.
2019-09-01 11:02:49,919  INFO ode.distributed.internal.InternalLocator: 530 - Starting peer location for Distribution Locator on 10.99.199.24[11235]
2019-09-01 11:02:49,925  INFO ode.distributed.internal.InternalLocator: 498 - Starting Distribution Locator on 10.99.199.24[11235]
2019-09-01 11:02:49,926  INFO distributed.internal.tcpserver.TcpServer: 242 - Locator was created at Sun Sep 01 11:02:49 PDT 2019
2019-09-01 11:02:49,927  INFO distributed.internal.tcpserver.TcpServer: 243 - Listening on port 11235 bound on address 0.0.0.0/0.0.0.0
2019-09-01 11:02:49,928  INFO ternal.membership.gms.locator.GMSLocator: 162 - GemFire peer location service starting.  Other locators: localhost[10334]  Locators preferred as coordinators: true  Network partition detection enabled: true  View persistence file: /Users/jblum/pivdev/spring-boot-data-geode/spring-geode-docs/build/locator11235view.dat
2019-09-01 11:02:49,928  INFO ternal.membership.gms.locator.GMSLocator: 416 - Peer locator attempting to recover from localhost/127.0.0.1:10334
2019-09-01 11:02:49,963  INFO ternal.membership.gms.locator.GMSLocator: 422 - Peer locator recovered initial membership of View[10.99.199.24(SpringLocatorOne:30043:locator)<ec><v0>:41000|0] members: [10.99.199.24(SpringLocatorOne:30043:locator)<ec><v0>:41000]
2019-09-01 11:02:49,963  INFO ternal.membership.gms.locator.GMSLocator: 407 - Peer locator recovered state from LocatorAddress [socketInetAddress=localhost/127.0.0.1:10334, hostname=localhost, isIpString=false]
2019-09-01 11:02:49,965  INFO ode.distributed.internal.InternalLocator: 644 - Starting distributed system
2019-09-01 11:02:50,007  INFO he.geode.internal.logging.LoggingSession:  82 -
---------------------------------------------------------------------------

  Licensed to the Apache Software Foundation (ASF) under one or more
  contributor license agreements.  See the NOTICE file distributed with this
  work for additional information regarding copyright ownership.

  The ASF licenses this file to You under the Apache License, Version 2.0
  (the "License"); you may not use this file except in compliance with the
  License.  You may obtain a copy of the License at

  https://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
  License for the specific language governing permissions and limitations
  under the License.

---------------------------------------------------------------------------
Build-Date: 2019-04-19 11:49:13 -0700
Build-Id: onichols 0
Build-Java-Version: 1.8.0_192
Build-Platform: Mac OS X 10.14.4 x86_64
Product-Name: Apache Geode
Product-Version: 1.9.0
Source-Date: 2019-04-19 11:11:31 -0700
Source-Repository: release/1.9.0
Source-Revision: c0a73d1cb84986d432003bd12e70175520e63597
Native version: native code unavailable
Running on: 10.99.199.24/10.99.199.24, 8 cpu(s), x86_64 Mac OS X 10.13.6
Communications version: 100
Process ID: 30077
User: jblum
Current dir: /Users/jblum/pivdev/spring-boot-data-geode/spring-geode-docs/build
Home dir: /Users/jblum
Command Line Parameters:
  -ea
  -Dspring.profiles.active=
  -Dspring.data.gemfire.locator.name=SpringLocatorTwo
  -Dspring.data.gemfire.locator.port=11235
  -Dlogback.log.level=INFO
  -javaagent:/Applications/IntelliJ IDEA 19 CE.app/Contents/lib/idea_rt.jar=51961:/Applications/IntelliJ IDEA 19 CE.app/Contents/bin
  -Dfile.encoding=UTF-8
Class Path:
...
..
.
2019-09-01 11:02:54,112  INFO ode.distributed.internal.InternalLocator: 661 - Locator started on 10.99.199.24[11235]
2019-09-01 11:02:54,113  INFO ode.distributed.internal.InternalLocator: 769 - Starting server location for Distribution Locator on 10.99.199.24[11235]
2019-09-01 11:02:54,134  INFO nt.internal.locator.wan.LocatorDiscovery: 138 - Locator discovery task exchanged locator information 10.99.199.24[11235] with localhost[10334]: {-1=[10.99.199.24[10334]]}.
2019-09-01 11:02:54,242  INFO .SpringBootApacheGeodeLocatorApplication:  61 - Started SpringBootApacheGeodeLocatorApplication in 6.137470354 seconds (JVM running for 6.667)
Press <enter> to exit!
----

Next, start up the second Locator app instance (you should see log output similar to above).  Then, connect to
the cluster of Locators using _Gfsh_:

.Cluster of Locators
[source,txt]
----
$ echo $GEMFIRE
/Users/jblum/pivdev/apache-geode-1.9.0

$ gfsh
    _________________________     __
   / _____/ ______/ ______/ /____/ /
  / /  __/ /___  /_____  / _____  /
 / /__/ / ____/  _____/ / /    / /
/______/_/      /______/_/    /_/    1.9.0

Monitor and Manage Apache Geode

gfsh>connect
Connecting to Locator at [host=localhost, port=10334] ..
Connecting to Manager at [host=10.99.199.24, port=1099] ..
Successfully connected to: [host=10.99.199.24, port=1099]

gfsh>list members
      Name       | Id
---------------- | ------------------------------------------------------------------------
SpringLocatorOne | 10.99.199.24(SpringLocatorOne:30043:locator)<ec><v0>:41000 [Coordinator]
SpringLocatorTwo | 10.99.199.24(SpringLocatorTwo:30077:locator)<ec><v1>:41001
----

Using our `SpringBootApacheGeodeCacheServerApplication` main class from the previous section, we can configure
and bootstrap an {geode-name} `CacheServer` application with Spring Boot and connect it to our cluster of Locators.

.SpringBootApacheGeodeCacheServerApplication class
[source,java]
----
include::{docs-src-dir}/org/springframework/geode/docs/example/app/server/SpringBootApacheGeodeCacheServerApplication.java[tags=class]
----

Simply enable the "clustered" Profile by using a IDE Run Profile Configuration similar to:

`-server -ea -Dspring.profiles.active=clustered -Dspring.data.gemfire.name=SpringServer -Dspring.data.gemfire.cache.server.port=41414 -Dlogback.log.level=INFO`

After the server starts up, you should see the new peer member in the cluster:

.Cluster with Spring Boot configured and bootstrapped {geode-name} `CacheServer`
[source,txt]
----
gfsh>list members
      Name       | Id
---------------- | ------------------------------------------------------------------------
SpringLocatorOne | 10.99.199.24(SpringLocatorOne:30043:locator)<ec><v0>:41000 [Coordinator]
SpringLocatorTwo | 10.99.199.24(SpringLocatorTwo:30077:locator)<ec><v1>:41001
SpringServer     | 10.99.199.24(SpringServer:30216)<v2>:41002
----

Finally, we can even start additional Locators and Servers connected to this cluster using _Gfsh_:

.Gfsh started Locators and Servers
[source,txt]
----
gfsh>start locator --name=GfshLocator --port=12345 --log-level=config
Starting a Geode Locator in /Users/jblum/pivdev/lab/GfshLocator...
......
Locator in /Users/jblum/pivdev/lab/GfshLocator on 10.99.199.24[12345] as GfshLocator is currently online.
Process ID: 30259
Uptime: 5 seconds
Geode Version: 1.9.0
Java Version: 1.8.0_192
Log File: /Users/jblum/pivdev/lab/GfshLocator/GfshLocator.log
JVM Arguments: -Dgemfire.default.locators=10.99.199.24[11235],10.99.199.24[10334] -Dgemfire.enable-cluster-configuration=true -Dgemfire.load-cluster-configuration-from-dir=false -Dgemfire.log-level=config -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/jblum/pivdev/apache-geode-1.9.0/lib/geode-core-1.9.0.jar:/Users/jblum/pivdev/apache-geode-1.9.0/lib/geode-dependencies.jar

gfsh>start server --name=GfshServer --server-port=45454 --log-level=config
Starting a Geode Server in /Users/jblum/pivdev/lab/GfshServer...
...
Server in /Users/jblum/pivdev/lab/GfshServer on 10.99.199.24[45454] as GfshServer is currently online.
Process ID: 30295
Uptime: 2 seconds
Geode Version: 1.9.0
Java Version: 1.8.0_192
Log File: /Users/jblum/pivdev/lab/GfshServer/GfshServer.log
JVM Arguments: -Dgemfire.default.locators=10.99.199.24[11235],10.99.199.24[12345],10.99.199.24[10334] -Dgemfire.start-dev-rest-api=false -Dgemfire.use-cluster-configuration=true -Dgemfire.log-level=config -XX:OnOutOfMemoryError=kill -KILL %p -Dgemfire.launcher.registerSignalHandlers=true -Djava.awt.headless=true -Dsun.rmi.dgc.server.gcInterval=9223372036854775806
Class-Path: /Users/jblum/pivdev/apache-geode-1.9.0/lib/geode-core-1.9.0.jar:/Users/jblum/pivdev/apache-geode-1.9.0/lib/geode-dependencies.jar

gfsh>list members
      Name       | Id
---------------- | ------------------------------------------------------------------------
SpringLocatorOne | 10.99.199.24(SpringLocatorOne:30043:locator)<ec><v0>:41000 [Coordinator]
SpringLocatorTwo | 10.99.199.24(SpringLocatorTwo:30077:locator)<ec><v1>:41001
SpringServer     | 10.99.199.24(SpringServer:30216)<v2>:41002
GfshLocator      | 10.99.199.24(GfshLocator:30259:locator)<ec><v3>:41003
GfshServer       | 10.99.199.24(GfshServer:30295)<v4>:41004
----

You must be careful to vary the ports and name of your peer members appropriately. With Spring, and Spring Boot
for {geode-name} (SBDG) in particular, it really is that easy!

[[geode-manager-applications]]
=== Building Manager Applications

As discussed in the previous sections above, it is possible to enable a Spring Boot configured and bootstrapped
{geode-name} peer member node in the cluster to function as a _Manager_.

An {geode-name} _Manager_ is a peer member node in the cluster running the Management Service, allowing the cluster
to be managed and monitored using JMX based tools, like _Gfsh_, _JConsole_ or _JVisualVM_, for instance. Any tool
that uses the JMX API can connect to and manage an {geode-name} cluster for whatever purpose.

The cluster may have more than 1 _Manager_ for redundancy.  Only server-side, peer member nodes in the cluster
may function as a _Manager_.  Therefore, a `ClientCache` application cannot be a _Manager_.

To create a _Manager_, you use the SDG `@EnableManager` annotation.

The 3 primary uses of the `@EnableManager` annotation to create a _Manager_ is:

.1 - CacheServer Manager Application
[source,java]
----
@SpringBootApplication
@CacheServerApplication(name = "CacheServerManagerApplication")
@EnableManager(start = true)
class CacheServerManagerApplication {
	// ...
}
----

.2 - Peer Cache Manager Application
[source,java]
----
@SpringBootApplication
@PeerCacheApplication(name = "PeerCacheManagerApplication")
@EnableManager(start = "true")
class SpringBootPeerCacheManagerApplication {
	// ...
}
----

.3 - Locator Manager Application
[source,java]
----
@SpringBootApplication
@LocatorApplication(name = "LocatorManagerApplication")
@EnableManager(start = true)
class LocatorManagerApplication {
	// ...
}
----

#1 creates a peer `Cache` instance with a `CacheServer` component accepting client connections along with
an embedded _Manager_ enabling JMX clients to connect.

#2 creates only a peer `Cache` instance along with an embedded _Manager_.  As a peer `Cache` with NO `CacheServer`
component, clients are not able to connect to this node.  It is merely a server managing data.

#3 creates a _Locator_ instance with an embedded _Manager_.

In all configuration arrangements, the _Manager_ was configured to start immediately.

TIP: See the `@EnableManager` annotation
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/EnableManager.html[Javadoc]
for additional configuration options.

As of {geode-name} 1.11.0, you must now include additional {geode-name} dependencies on your Spring Boot application
classpath to make your application a proper {geode-name} _Manager_ in the cluster, particularly if you are also enabling
the embedded HTTP service in the _Manager_.

The required dependencies are:

.Additional, required Manager dependencies expressed in Gradle
[source,groovy]
----
runtime "org.apache.geode:geode-http-service"
runtime "org.apache.geode:geode-web"
runtime "org.springframework.boot:spring-boot-starter-jetty"
----

The embedded HTTP service (implemented with the Eclipse Jetty Servlet Container), runs the Management (Admin) REST API,
which is used by tooling, such as _Gfsh_, to connect to the cluster over HTTP.  In addition, it also enables the
{geode-name} {apache-geode-docs}/tools_modules/pulse/pulse-overview.html[Pulse] Monitoring Tool (and Web application)
to run.

Even if you do not start the embedded HTTP service, a _Manager_ still requires the `geode-http-service`, `geode-web`
and `spring-boot-starter-jetty` dependencies.

Optionally, you may also include the `geode-pulse` dependency, as follows:

.Additional, optional Manager depdendencies expressed in Gradle
[source,groovy]
----
runtime "org.apache.geode:geode-pulse"
----

The `geode-pulse` dependency is only required if you want the _Manager_ to automatically start
the {geode-name} {apache-geode-docs}/tools_modules/pulse/pulse-overview.html[Pulse] Monitoring Tool.  _Pulse_ enables
you to view the nodes of your {geode-name} cluster and monitor them in realtime.
