[[geode-data-access-region-templates]]
== Data Access with GemfireTemplate

There are several ways to access data stored in Apache Geode.

For instance, developers may choose to use the {apache-geode-javadoc}/org/apache/geode/cache/Region.html[Region API]
directly. If developers are driven by the application's domain context, they might choose to leverage the power of
{spring-data-commons-docs-html}/#repositories[Spring Data Repositories] instead.

While using the _Region_ API directly offers flexibility, it couples your application to Apache Geode, which is usually
undesirable and unnecessary.  While using Spring Data _Repositories_ provides a very powerful and convenient abstraction,
you give up flexibility provided by a lower level API.

A good comprise is to use the _Template_ pattern.  Indeed, this pattern is consistently and widely used throughout
the entire Spring portfolio.

For example, there is the {spring-framework-javadoc}/org/springframework/jdbc/core/JdbcTemplate.html[JdbcTemplate]
and {spring-framework-javadoc}/org/springframework/jms/core/JmsTemplate.html[JmsTemplate], which are provided by
the core Spring Framework.

Other Spring Data modules, such as Spring Data Redis, offer the
https://docs.spring.io/spring-data/redis/docs/current/api/org/springframework/data/redis/core/RedisTemplate.html[RedisTemplate],
and Spring Data for Apache Geode/Pivotal GemFire (SDG) offers the
{spring-data-gemfire-javadoc}/org/springframework/data/gemfire/GemfireTemplate.html[GemfireTemplate].

The `GemfireTemplate` provides a highly consistent and familiar API to perform data access operations on Apache Geode
or Pivotal GemFire cache `Regions`.

`GemfireTemplate` offers:

1. Simple, consistent and convenient data access API to perform CRUD and basic query operations on cache Regions.
2. Use of Spring Framework's consistent, data access {spring-framework-docs}/data-access.html#dao-exceptions[Exception Hierarchy].
3. Automatic enlistment in the presence of local, cache transactions.
4. Protection from {apache-geode-javadoc}/org/apache/geode/cache/Region.html[Region API] breaking changes.

Given these conveniences, Spring Boot for Apache Geode & Pivotal GemFire (SBDG) will auto-configure `GemfireTemplate`
beans for each Region present in the GemFire/Geode cache.

Additionally, SBDG is careful not to create a `GemfireTemplate` if the user has already declared a `GemfireTemplate`
bean in the Spring `ApplicationContext` for a given Region.

[[geode-data-access-region-templates-explicit-declaration]]
=== Explicitly Declared Regions

Given an explicitly declared Region bean definition:

[source,java]
----
@Configuration
class GemFireConfiguration {

  @Bean("Example")
  ClientRegionFactoryBean<?, ?> exampleRegion (GemFireCache gemfireCache) {
    ...
  }
}
----

SBDG will automatically create a `GemfireTemplate` bean for the "Example" Region using a bean name "exampleTemplate".
SBDG will name the `GemfireTemplate` bean after the Region by converting the first letter in the Region's name
to lowercase and appending the word "Template" to the bean name.

In a managed Data Access Object (DAO), I can inject the Template, like so:

[source,java]
----
@Repository
class ExampleDataAccessObject {

  @Autowired
  @Qualifier("exampleTemplate")
  private GemfireTemplate exampleTemplate;

}
----

It's advisable, especially if you have more than 1 Region, to use the `@Qualifier` annotation to qualify which
`GemfireTemplate` bean you are specifically referring as demonstrated above.

[[geode-data-access-region-templates-entity-defined]]
=== Entity-defined Regions

SBDG auto-configures `GemfireTemplate` beans for Entity-defined Regions.

Given the following entity class:

[source,java]
----
@Region("Customers")
class Customer {
  ...
}
----

And configuration:

[source,java]
----
@Configuration
@EnableEntityDefinedRegions(basePackageClasses = Customer.class}
class GemFireConfiguration {
  ...
}
----

SBDG auto-configures a `GemfireTemplate` bean for the "Customers" Region named "customersTemplate", which you can then
inject into an application component:

[source,java]
----
@Service
class CustomerService {

  @Bean
  @Qualifier("customersTemplate")
  private GemfireTemplate customersTemplate;

}
----

Again, be careful to qualify the `GemfireTemplate` bean injection if you have multiple Regions, whether declared
explicitly or implicitly, such as when using the `@EnableEntityDefineRegions` annotation.

[[geode-data-access-region-templates-caching-defined]]
=== Caching-defined Regions

SBDG auto-configures `GemfireTemplate` beans for Caching-defined Regions.

When you are using Spring Framework's {spring-framework-docs}/integration.html#cache[Cache Abstraction] backed by
either Apache Geode or Pivotal GemFire, 1 of the requirements is to configure Regions for each of the caches specified
in the {spring-framework-docs}integration.html#cache-annotations[Caching Annotations] of your application service
components.

Fortunately, SBDG makes enabling and configuring caching easy and <<geode-caching-provider,automatic>> out-of-the-box.

Given a cacheable application service component:

[source,java]
----
@Service
class CacheableCustomerService {

  @Bean
  @Qualifier("customersByNameTemplate")
  private GemfireTemplate customersByNameTemplate;

  @Cacheable("CustomersByName")
  public Customer findBy(String name) {
    return toCustomer(customersByNameTemplate.query("name = " + name));
  }
}
----

And configuration:

[source,java]
----
@Configuration
@EnableCachingDefinedRegions
class GemFireConfiguration {

  @Bean
  public CustomerService customerService() {
    return new CustomerService();
  }
}
----


SBDG auto-configures a `GemfireTemplate` bean named "customersByNameTemplate" used to perform data access operations
on the "CustomersByName" (`@Cacheable`) Region, which you can inject into any managed application component,
as shown above.

Again, be careful to qualify the `GemfireTemplate` bean injection if you have multiple Regions, whether declared
explicitly or implicitly, such as when using the `@EnableCachingDefineRegions` annotation.

WARNING: There are certain cases where autowiring (i.e. injecting) `GemfireTemplate` beans auto-configured by SBDG
for Caching-defined Regions into your application components will not always work!  This has to do with the Spring
Container bean creation process.  In those case you may need to lazily lookup the `GemfireTemplate` as needed, using
`applicationContext.getBean("customersByNameTemplate", GemfireTemplate.class)`.  This is certainly not ideal but works
when autowiring does not.

[[geode-data-access-region-templates-native-defined]]
=== Native-defined Regions

SBDG will even auto-configure `GemfireTemplate` beans for Regions defined using Apache Geode and Pivotal GemFire native
configuration meta-data, such as `cache.xml`.

Given the following GemFire/Geode native `cache.xml`:

[source,xml]
----
<?xml version="1.0" encoding="UTF-8"?>
<client-cache xmlns="http://geode.apache.org/schema/cache"
			  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			  xsi:schemaLocation="http://geode.apache.org/schema/cache http://geode.apache.org/schema/cache/cache-1.0.xsd"
			  version="1.0">

	<region name="Example" refid="LOCAL"/>

</client-cache>
----

And Spring configuration:

[source,java]
----
@Configuration
@EnableGemFireProperties(cacheXmlFile = "cache.xml")
class GemFireConfiguration {
  ...
}
----

SBDG will auto-configure a `GemfireTemplate` bean named "exampleTemplate" after the "Example" Region defined in
`cache.xml`. This Template can be injected like any other Spring managed bean:

[source,java]
----
@Service
class ExampleService {

  @Autowired
  @Qualifier("exampleTemplate")
  private GemfireTemplate exampleTemplate;

}
----

The same rules as above apply when multiple Regions are present.

[[geode-data-access-region-templates-rules]]
=== Template Creation Rules

Fortunately, SBDG is careful not to create a `GemfireTemplate` bean for a Region if a Template by the same name
already exists. For example, if you defined and declared the following configuration:

[source,java]
----
@Configuration
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
class GemFireConfiguration {

  @Bean
  public GemfireTemplate customersTemplate(GemFireCache cache) {
    return new GemfireTemplate(cache.getRegion("/Customers");
  }
}
----

Using our same Customers class, as above:

[source,java]
----
@Region("Customers")
class Customer {
  ...
}
----

Because you explicitly defined the "customersTemplate" bean, SBDG will not create a Template for the "Customers" Region
automatically. This applies regardless of how the Region was created, whether using `@EnableEntityDefinedRegions`,
`@EnableCachingDefinedRegions`, declaring Regions explicitly or defining Regions natively.

Even if you name the Template differently from the Region for which the Template was configured, SBDG will conserve
resources and not create the Template.

For example, suppose you named the `GemfireTemplate` bean, "vipCustomersTemplate", even though the Region name
is "Customers", based on the `@Region` annotated `Customer` class, which specified Region "Customers".

With the following configuration, SBDG is still careful not to create the Template:

[source,java]
----
@Configuration
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
class GemFireConfiguration {

  @Bean
  public GemfireTemplate vipCustomersTemplate(GemFireCache cache) {
    return new GemfireTemplate(cache.getRegion("/Customers");
  }
}
----

SBDG identifies that your "vipCustomersTemplate" is the Template used with the "Customers" Region and SBDG will not
create the "customersTemplate" bean, which would result in 2 `GemfireTemplate` beans for the same Region.

NOTE: The name of your Spring bean defined in JavaConfig is the name of the method if the Spring bean is not explicitly
named using the `name` (or `value`) attribute of the `@Bean` annotation.
