396 lines
17 KiB
Plaintext
396 lines
17 KiB
Plaintext
[[geode-auto-configuration-annotations]]
|
|
== Auto-configuration vs. Annotation-based configuration
|
|
|
|
The question most often asked is, "_What Spring Data for Apache Geode/Pivotal GemFire annotations can I use,
|
|
or must I use, when developing Apache Geode or Pivotal GemFire applications with Spring Boot?_"
|
|
|
|
This section will answer this question and more.
|
|
|
|
Readers should refer to the complimentary sample, link:guides/boot-configuration.html[Spring Boot Auto-configuration for Apache Geode & Pivotal GemFire],
|
|
which showcases the _auto-configuration_ provided by Spring Boot for Apache Geode/Pivotal GemFire in action.
|
|
|
|
[[geode-autoconfiguration-annotations-background]]
|
|
=== Background
|
|
|
|
To help answer this question, we must start by reviewing the complete collection of available
|
|
Spring Data for Apache Geode/Pivotal GemFire (SDG) annotations. These annotations are provided in the
|
|
{spring-data-geode-javadoc}/org/springframework/data/gemfire/config/annotation/package-summary.html[org.springframework.data.gemfire.config.annotation]
|
|
package. Most of the pertinent annotations begin with `@Enable...`, except for the base annotations:
|
|
`@ClientCacheApplication`, `@PeerCacheApplication` and `@CacheServerApplication`.
|
|
|
|
By extension, Spring Boot for Apache Geode/Pivotal GemFire (SBDG) builds on SDG's Annotation-based configuration model
|
|
to implement _auto-configuration_ and apply Spring Boot's core concepts, like "_convention over configuration_",
|
|
enabling GemFire/Geode applications to be built with Spring Boot reliably, quickly and easily.
|
|
|
|
SDG provides this Annotation-based configuration model to, first and foremost, give application developers "_choice_"
|
|
when building Spring applications using either Apache Geode or Pivotal GemFire. SDG makes no assumptions about what
|
|
application developers are trying to do and fails fast anytime the configuration is ambiguous, giving users immediate
|
|
feedback.
|
|
|
|
Second, SDG's Annotations were meant to get application developers up and running quickly and reliably with ease. SDG
|
|
accomplishes this by applying sensible defaults so application developers do not need to know, or even have to learn,
|
|
all the intricate configuration details and tooling provided by GemFire/Geode to accomplish simple tasks,
|
|
e.g. build a prototype.
|
|
|
|
So, SDG is all about "choice" and SBDG is all about "convention". Together these frameworks provide application
|
|
developers with convenience and reliability to move quickly and easily.
|
|
|
|
To learn more about the motivation behind SDG's Annotation-based configuration model, refer to the
|
|
{spring-data-gemfire-docs-html}/#bootstrap-annotation-config-introduction[Reference Documentation].
|
|
|
|
[[geode-autoconfiguration-annotations-conventions]]
|
|
=== Conventions
|
|
|
|
Currently, SBDG provides _auto-configuration_ for the following features:
|
|
|
|
* `ClientCache`
|
|
* Caching with Spring's Cache Abstraction
|
|
* Continuous Query
|
|
* Function Execution & Implementation
|
|
* Logging
|
|
* PDX
|
|
* `GemfireTemplate`
|
|
* Spring Data Repositories
|
|
* Security (Client/Server Auth & SSL)
|
|
* Spring Session
|
|
|
|
Technically, this means the following SDG Annotations are not required to use the features above:
|
|
|
|
* `@ClientCacheApplication`
|
|
* `@EnableGemfireCaching` (or by using Spring Framework's `@EnableCaching`)
|
|
* `@EnableContinuousQueries`
|
|
* `@EnableGemfireFunctionExecutions`
|
|
* `@EnableGemfireFunctions`
|
|
* `@EnableLogging`
|
|
* `@EnablePdx`
|
|
* `@EnableGemfireRepositories`
|
|
* `@EnableSecurity`
|
|
* `@EnableSsl`
|
|
* `@EnableGemFireHttpSession`
|
|
|
|
Since SBDG auto-configures these features for you, then the above annotations are not strictly required. Typically, you
|
|
would only declare one of theses annotations when you want to "override" Spring Boot's conventions, expressed in
|
|
_auto-configuration_, and "customize" the behavior of the feature.
|
|
|
|
[[geode-autoconfiguration-annotations-overriding]]
|
|
=== Overriding
|
|
|
|
In this section, we cover a few examples to make the behavior when overriding more apparent.
|
|
|
|
[[geode-autoconfiguration-annotations-overriding-caches]]
|
|
==== Caches
|
|
|
|
By default, SBDG provides you with a `ClientCache` instance. Technically, SBDG accomplishes this by annotating
|
|
an auto-configuration class with `@ClientCacheApplication`, internally.
|
|
|
|
It is by convention that we assume most application developers' will be developing Spring Boot applications
|
|
using Apache Geode or Pivotal GemFire as "client" applications in GemFire/Geode's client/server topology. This is
|
|
especially true as users migrate their applications to a managed environment, such as Pivotal CloudFoundry (PCF)
|
|
using Pivotal Cloud Cache (PCC).
|
|
|
|
Still, users are free to "override" the default settings and declare their Spring applications to be actual peer `Cache`
|
|
members of a cluster, instead.
|
|
|
|
For example:
|
|
|
|
[source,java]
|
|
----
|
|
@SpringBootApplication
|
|
@CacheServerApplication
|
|
class MySpringBootPeerCacheServerApplication { ... }
|
|
----
|
|
|
|
By declaring the `@CacheServerApplication` annotation, you effectively override the SBDG default. Therefore, SBDG
|
|
will not provide a `ClientCache` instance because you have informed SBDG of exactly what you want, i.e. a peer `Cache`
|
|
instance hosting an embedded `CacheServer` that allows client connections.
|
|
|
|
However, you then might ask, "_Well, how do I customize the ClientCache instance when developing client applications
|
|
without explicitly declaring the @ClientCacheApplication annotation, then?_"
|
|
|
|
First, you are entirely allowed to "customize" the `ClientCache` instance by explicitly declaring the
|
|
`@ClientCacheApplication` annotation in your Spring Boot application configuration, and set specific attributes
|
|
as needed. However, you should be aware that by explicitly declaring this annotation, or any of the other
|
|
auto-configured annotations by default, then you assume all the responsibility that comes with it since you have
|
|
effectively overridden the auto-configuration. One example of this is Security, which we touch on more below.
|
|
|
|
The most ideal way to "customize" the configuration of any feature is by way of the well-known and documented
|
|
<<geode-configuration-metadata,Properties>>, specified in Spring Boot `application.properties` (the "convention"),
|
|
or by using a {spring-data-gemfire-docs-html}/#bootstrap-annotation-config-configurers[Configurer].
|
|
|
|
See the <<geode-clientcache-applications,Reference Guide>> for more details.
|
|
|
|
[[geode-autoconfiguration-annotations-overriding-security]]
|
|
==== Security
|
|
|
|
Like the `@ClientCacheApplication` annotation, the `@EnableSecurity` annotation is not strictly required, not unless
|
|
you want to override and customize the defaults.
|
|
|
|
Outside a managed environment, the only Security configuration required is specifying a username and password. You do
|
|
this using the well-known and document SDG username/password properties in Spring Boot `application.properties`,
|
|
like so:
|
|
|
|
.Required Security Properties in a Non-Manage Envionment
|
|
[source,properties]
|
|
----
|
|
spring.data.gemfire.security.username=MyUser
|
|
spring.data.gemfire.security.password=Secret
|
|
----
|
|
|
|
You do not need to explicitly declare the `@EnableSecurity` annotation just to specify Security configuration
|
|
(e.g. username/password).
|
|
|
|
Inside a managed environment, such as Pivotal CloudFoundry (PCF) when using Pivotal Cloud Cache (PCC), SBDG is able to
|
|
introspect the environment and configure Security (Auth) completely without the need to specify any configuration,
|
|
usernames/passwords, or otherwise. This is due in part because PCF supplies the security details in the VCAP
|
|
environment when the app is deployed to PCF and bound to services (e.g. PCC).
|
|
|
|
So, in short, you do not need to explicitly declare the `@EnableSecurity` annotation (or the `@ClientCacheApplication`
|
|
for that matter).
|
|
|
|
However, if you do explicitly declare either the `@ClientCacheApplication` and/or `@EnableSecurity` annotations,
|
|
guess what, you are now responsible for this configuration and SBDG's _auto-configuration_ no longer applies.
|
|
|
|
While explicitly declaring `@EnableSecurity` makes more sense when "overriding" the SBDG Security _auto-configuration_,
|
|
explicitly declaring the `@ClientCacheApplication` annotation most likely makes less sense with regard to its impact
|
|
on Security configuration.
|
|
|
|
This is entirely due to the internals of GemFire/Geode, which in certain cases, like Security, not even Spring
|
|
is able to completely shield users from the nuances of GemFire/Geode's configuration.
|
|
|
|
Both Auth and SSL must be configured before the cache instance (whether a `ClientCache` or a peer `Cache`,
|
|
it does not matter) is created. Technically, this is because Security is enabled/configured during the "construction"
|
|
of the cache. And, the cache pulls the configuration from JVM System properties that must be set before the cache
|
|
is constructed.
|
|
|
|
Structuring the "exact" order of the _auto-configuration_ classes provided by SBDG when the classes are triggered,
|
|
is no small feat. Therefore, it should come as no surprise to learn that the Security _auto-configuration_ classes
|
|
in SBDG must be triggered before the ClientCache _auto-configuration_ class, which is why a ClientCache instance cannot
|
|
"auto" authenticate properly in PCC when the `@ClientCacheApplication` is explicitly declared without some assistance
|
|
(i.e. you must also explicitly declare the `@EnableSecurity` annotation in this case since you overrode the
|
|
_auto-configuration_ of the cache, and, well, implicitly Security as well).
|
|
|
|
Again, this is due to the way Security (Auth) and SSL meta-data must be supplied to GemFire/Geode.
|
|
|
|
See the <<geode-security,Reference Guide>> for more details.
|
|
|
|
[[geode-autoconfiguration-annotations-extension]]
|
|
=== Extension
|
|
|
|
Most of the time, many of the other auto-configured annotations for CQ, Functions, PDX, Repositories, and so on, do not
|
|
need to ever be declared explicitly.
|
|
|
|
Many of these features are enabled automatically by having SBDG or other libraries (e.g. Spring Session)
|
|
on the classpath, or are enabled based on other annotations applied to beans in the Spring `ApplicationContext`.
|
|
|
|
Let's review a few examples.
|
|
|
|
[[geode-autoconfiguration-annotations-extension-caching]]
|
|
==== Caching
|
|
|
|
It is rarely, if ever, necessary to explicitly declare either the Spring Framework's `@EnableCaching`, or the SDG
|
|
specific `@EnableGemfireCaching` annotation, in Spring configuration when using SBDG. SBDG automatically "enables"
|
|
caching and configures the SDG `GemfireCacheManager` for you.
|
|
|
|
You simply only need to focus on which application service components are appropriate for caching:
|
|
|
|
.Service Caching
|
|
[source,java]
|
|
----
|
|
@Service
|
|
class CustomerService {
|
|
|
|
@Autowired
|
|
private CustomerRepository customerRepository;
|
|
|
|
@Cacheable("CustomersByName")
|
|
public Customer findBy(String name) {
|
|
return customerRepository.findByName(name);
|
|
}
|
|
}
|
|
----
|
|
|
|
Of course, it is necessary to create GemFire/Geode Regions backing the caches declared in your application service
|
|
components (e.g. "CustomersByName") using Spring's Caching Annotations (e.g. `@Cacheable), or alternatively,
|
|
JSR-107, JCache annotations (e.g. `@CacheResult`).
|
|
|
|
You can do that by defining each Region explicitly, or more conveniently, you can simply use:
|
|
|
|
.Configuring Caches (Regions)
|
|
[source,java]
|
|
----
|
|
@SpringBootApplication
|
|
@EnableCachingDefinedRegions
|
|
class Application { ... }
|
|
----
|
|
|
|
`@EnableCachingDefinedRegions` is optional, provided for convenience, and complimentary to caching when used
|
|
rather than necessary.
|
|
|
|
See the <<geode-caching-provider,Reference Guide>> for more details.
|
|
|
|
[[geode-autoconfiguration-annotations-extension-cq]]
|
|
==== Continuous Query
|
|
|
|
It is rarely, if ever, necessary to explicitly declare the SDG `@EnableContinuousQueries` annotation. Instead,
|
|
you should be focused on defining your application queries and worrying less about the plumbing.
|
|
|
|
For example:
|
|
|
|
.Defining Queries for CQ
|
|
[source,java]
|
|
----
|
|
@Component
|
|
public class TemperatureMonitor extends AbstractTemperatureEventPublisher {
|
|
|
|
@ContinuousQuery(name = "BoilingTemperatureMonitor",
|
|
query = "SELECT * FROM /TemperatureReadings WHERE temperature.measurement >= 212.0")
|
|
public void boilingTemperatureReadings(CqEvent event) {
|
|
publish(event, temperatureReading -> new BoilingTemperatureEvent(this, temperatureReading));
|
|
}
|
|
|
|
@ContinuousQuery(name = "FreezingTemperatureMonitor",
|
|
query = "SELECT * FROM /TemperatureReadings WHERE temperature.measurement <= 32.0")
|
|
public void freezingTemperatureReadings(CqEvent event) {
|
|
publish(event, temperatureReading -> new FreezingTemperatureEvent(this, temperatureReading));
|
|
}
|
|
}
|
|
----
|
|
|
|
Of course, GemFire/Geode CQ only applies to clients.
|
|
|
|
See the <<geode-continuous-query,Reference Guide>> for more details.
|
|
|
|
[[geode-autoconfiguration-annotations-extension-functions]]
|
|
==== Functions
|
|
|
|
It is rarely, if ever, necessary to explicitly declare either the `@EnableGemfireFunctionExecutions`
|
|
or `@EnableGemfireFunctions` annotations. SBDG provides _auto-configuration_ for both Function implementations
|
|
and executions. You simply need to define the implementation:
|
|
|
|
.Function Implementation
|
|
[source,java]
|
|
----
|
|
@Component
|
|
class GemFireFunctions {
|
|
|
|
@GemfireFunction
|
|
Object exampleFunction(Object arg) {
|
|
...
|
|
}
|
|
}
|
|
----
|
|
|
|
And then define the execution:
|
|
|
|
.Function Execution
|
|
[source,java]
|
|
----
|
|
@OnRegion(region = "Example")
|
|
interface GemFireFunctionExecutions {
|
|
|
|
Object exampleFunction(Object arg);
|
|
}
|
|
----
|
|
|
|
SBDG will automatically find, configure and register Function Implementations (POJOs) in GemFire/Geode as proper
|
|
`Functions` as well as create Executions proxies for the Interfaces which can then be injected into application service
|
|
components to invoke the registered `Functions` without needing to explicitly declare the enabling annotations.
|
|
The application Function Implementations & Executions (Interfaces) should simply exist below the `@SpringBootApplication`
|
|
annotated main class.
|
|
|
|
See the <<[geode-functions,Reference Guide>> for more details.
|
|
|
|
[[geode-autoconfiguration-annotations-extension-pdx]]
|
|
==== PDX
|
|
|
|
It is rarely, if ever, necessary to explicitly declare the `@EnablePdx` annotation since SBDG _auto-configures_ PDX
|
|
by default. SBDG automatically configures the SDG `MappingPdxSerializer` as the default `PdxSerializer` as well.
|
|
|
|
It is easy to customize the PDX configuration by setting the appropriate <<geode-configuration-metadata,Properties>>
|
|
(search for "PDX") in Spring Boot `application.properties`.
|
|
|
|
See the <<geode-data-serialization,Reference Guide>> for more details.
|
|
|
|
[[geode-autoconfiguration-annotations-extension-repositories]]
|
|
==== Spring Data Repositories
|
|
|
|
It is rarely, if ever, necessary to explicitly declare the `@EnableGemfireRepositories` annotation since SBDG
|
|
_auto-configures_ Spring Data (SD) _Repositories_ by default.
|
|
|
|
You simply only need to define your Repositories and get cranking:
|
|
|
|
.Customer's Repository
|
|
[source,java]
|
|
----
|
|
interface CustomerRepository extends CrudRepository<Customer, Long> {
|
|
|
|
Customer findByName(String name);
|
|
|
|
}
|
|
----
|
|
|
|
SBDG finds the _Repository_ interfaces defined in your application, proxies them, and registers them as beans
|
|
in the Spring `ApplicationContext`. The _Repositories_ may be injected into other application service components.
|
|
|
|
It is sometimes convenient to use the `@EnableEntityDefinedRegions` along with SD _Repositories_ to identify
|
|
the entities used by your application and define the Regions used by the SD _Repository_ infrastructure to persist
|
|
the entity's state. The `@EnableEntityDefinedRegions` annotation is optional, provided for convenience,
|
|
and complimentary to the `@EnableGemfireRepositories` annotation.
|
|
|
|
See the <<geode-repositories,Reference Guide>> for more details.
|
|
|
|
[[geode-autoconfiguration-annotations-explicit]]
|
|
=== Explicit Configuration
|
|
|
|
Most of the other annotations provided in SDG are focused on particular application concerns, or enable certain
|
|
GemFire/Geode features, rather than being a necessity.
|
|
|
|
A few examples include:
|
|
|
|
* `@EnableAutoRegionLookup`
|
|
* `@EnableBeanFactoryLocator`
|
|
* `@EnableCacheServer(s)`
|
|
* `@EnableCachingDefinedRegions`
|
|
* `@EnableClusterConfiguration`
|
|
* `@EnableClusterDefinedRegions`
|
|
* `@EnableCompression`
|
|
* `@EnableDiskStore(s)`
|
|
* `@EnableEntityDefinedRegions`
|
|
* `@EnableEviction`
|
|
* `@EnableExpiration`
|
|
* `@EnableGatewayReceiver`
|
|
* `@EnableGatewaySender(s)`
|
|
* `@EnableGemFireAsLastResource`
|
|
* `@EnableHttpService`
|
|
* `@EnableIndexing`
|
|
* `@EnableOffHeap`
|
|
* `@EnableLocator`
|
|
* `@EnableManager`
|
|
* `@EnableMemcachedServer`
|
|
* `@EnablePool(s)`
|
|
* `@EnableRedisServer`
|
|
* `@EnableStatistics`
|
|
* `@UseGemFireProperties`
|
|
|
|
None of these annotations are necessary and none are auto-configured by SBDG. They are simply at the
|
|
application developers disposal if and when needed. This also means none of these annotations are in conflict with
|
|
any SBDG _auto-configuration_.
|
|
|
|
[[geode-autoconfiguration-annotations-summary]]
|
|
=== Summary
|
|
|
|
In conclusion, it is important to understand where SDG ends and SBDG begins. It all begins with the _auto-configuration_
|
|
provided by SBDG out-of-the-box.
|
|
|
|
If a feature is not covered by SBDG's _auto-configuration_, then you are responsible for enabling and configuring
|
|
the feature appropriately, as needed by your application (e.g. `@EnableRedisServer`).
|
|
|
|
In other cases, you might also want to explicitly declare a complimentary annotation (e.g. `@EnableEntityDefinedRegions`)
|
|
for convenience, since there is no convention or "opinion" provided by SBDG out-of-the-box.
|
|
|
|
In all remaining cases, it boils down to understanding how GemFire/Geode works under-the-hood. While we go to great
|
|
lengths to shield users from as many details as possible, it is not feasible or practical to address all matters,
|
|
e.g. cache creation and Security.
|
|
|
|
Hope this section provided some relief and clarity.
|