5. Auto-configuration

The following Spring Framework, Spring Data for Apache Geode & Pivotal GemFire (SDG) and Spring Session for Apache Geode & Pivotal GemFire (SSDG) Annotations are implicitly declared by Spring Boot for Apache Geode & Pivotal GemFire’s (SBDG) Auto-configuration.

[Note]Note

This means you DO NOT need to explicitly declare any of these Annotations on your @SpringBootApplication class since they are provided by SBDG already. The only reason you would explicitly declare any of these Annotations is if you wanted to "override" Spring Boot’s, and in particular, SBDG’s Auto-configuration. Otherwise, it is unnecessary!

[Tip]Tip

You should read the chapter in Spring Boot’s Reference Guide on Auto-configuration.

[Tip]Tip

You should review the chapter in Spring Data for Apache Geode and Pivotal GemFire’s (SDG) Reference Guide on Annotation-based Configuration. For a quick reference, or an overview of Annotation-based Configuration, see here.

5.1 Customizing Auto-configuration

You might ask how I can customize the Auto-configuration provided by SBDG if I do not explicitly declare the annotation?

For example, you mat want to customize the member’s "name". You know that the @ClientCacheApplication annotation provides the name attribute so you can set the client member’s "name". But SBDG has already implicitly declared the @ClientCacheApplication annotation via Auto-configuration on your behalf. What do you do?

Well, SBDG supplies a few very useful Annotations in this case.

For example, to set the (client or peer) member’s name, you can use the @UseMemberName annotation, like so:

Setting the member’s name using @UseMemberName

@SpringBootApplication
@UseMemberName("MyMemberName")
class SpringBootClientCacheApplication { ... }

Alternatively, you could set the spring.application.name or the spring.data.gemfire.name property in Spring Boot application.properties

Setting the member’s name using the spring.application.name property. 

# Spring Boot application.properties

spring.application.name = MyMemberName

Or:

Setting the member’s name using the spring.data.gemfire.cache.name property. 

# Spring Boot application.properties

spring.data.gemfire.cache.name = MyMemberName

In general, there are 3 ways to customize configuration, even in the context of SBDG’s Auto-configuration:

  1. Using Annotations provided by SBDG for common and popular concerns (e.g. naming client or peer members with @UseMemberName, or enabling durable clients with @EnableDurableClient).
  2. Using well-known and documented Properties (e.g. spring.application.name, or spring.data.gemfire.name, or spring.data.gemfire.cache.name).
  3. Using Configurers (e.g. ClientCacheConfigurer).
[Tip]Tip

For the complete list of documented Properties, see here.

5.2 Disabling Auto-configuration

Disabling Spring Boot Auto-configuration is explained in detail in Spring Boot’s Reference Guide.

Disabling SBDG Auto-confiugration was also explained in detail.

In a nutshell, if you want to disable any Auto-configuration provided by either Spring Boot or SBDG, then you can declare your intent in the @SpringBootApplication annotation, like so:

Disabling Specific Auto-configuration Classes. 

@SpringBootApplication(
  exclude = { DataSourceAutoConfiguration.class, PdxAutoConfiguration.class }
)
class SpringBootClientCacheApplication { ... }

[Warning]Warning

Make sure you understand what you are doing when you are "disabling" Auto-configuration.

5.3 Overriding Auto-configuration

Overriding SBDG Auto-configuration was explained in detail as well.

In a nutshell, if you want to override the default Auto-configuration provided by SBDG then you must annotate your @SpringBootApplication class with your intent.

For example, say you want to configure and bootstrap an Apache Geode or Pivotal GemFire CacheServer application (a peer; not a client), then you would:

Overriding the default ClientCache Auto-Configuration by configuring & bootstrapping a CacheServer application. 

@SpringBootApplication
@CacheServerApplication
class SpringBootCacheServerApplication { ... }

Even when you explicitly declare the @ClientCacheApplication annotation on your @SpringBootApplication class, like so:

Overriding by explicitly declaring @ClientCacheApplication

@SpringBootApplication
@ClientCacheApplication
class SpringBootClientCacheApplication { ... }

You are overriding SBDG’s Auto-configuration of the ClientCache instance. As a result, you now have also implicitly consented to being responsible for other aspects of the configuration (e.g. Security)! Why?

This is because in certain cases, like Security, certain aspects of Security configuration (e.g. SSL) must be configured before the cache instance is created. And, Spring Boot always applies user configuration before Auto-configuration partially to determine what needs to be auto-configured in the first place.

[Warning]Warning

Especially make sure you understand what you are doing when you are "overriding" Auto-configuration.

5.4 Replacing Auto-configuration

We will simply refer you to the Spring Boot Reference Guide on replacing Auto-configuration. See here.

5.5 Auto-configuration Explained

This section covers the SBDG provided Auto-configuration classes corresponding to the SDG Annotations in more detail.

To review the complete list of SBDG Auto-confiugration classes, see here.

5.5.1 @ClientCacheApplication

[Note]Note

The ClientCacheAutoConfiguration class corresponds to the @ClientCacheApplication annotation.

SBDG starts with the opinion that application developers will primarily be building Apache Geode or Pivotal GemFire client applications using Spring Boot.

Technically, this means building Spring Boot applications with either an Apache Geode or Pivotal GemFire ClientCache instance connected to a dedicated cluster of Apache Geode or Pivotal GemFire servers that manage the data as part of a client/server topology.

By way of example, this means you do not need to explicitly declare and annotate your @SpringBootApplication class with SDG’s @ClientCacheApplication annotation, like so:

Do Not Do This. 

@SpringBootApplication
@ClientCacheApplication
class SpringBootClientCacheApplication { ... }

This is because SBDG’s provided Auto-configuration class is already meta-annotated with SDG’s @ClientCacheApplication annotation. Therefore, you simply need:

Do This. 

@SpringBootApplication
class SpringBootClientCacheApplication { ... }

[Tip]Tip

Refer to SDG’s Referene Guide for more details on Apache Geode or Pivotal GemFire cache applications, and client/server applications in particular.

5.5.2 @EnableGemfireCaching

[Note]Note

The CachingProviderAutoConfiguration class corresponds to the @EnableGemfireCaching annotation.

If you simply used the core Spring Framework to configure either Apache Geode or Pivotal GemFire as a caching provider in Spring’s Cache Abstraction, you would need to do this:

Configuring caching using the Spring Framework. 

@SpringBootApplication
@EnableCaching
class CachingUsingApacheGeodeConfiguration {

  @Bean
  GemfireCacheManager cacheManager(GemFireCache cache) {

      GemfireCacheManager cacheManager = new GemfireCacheManager();

      cacheManager.setCache(cache);

      return cacheManager;
  }
}

If you were using Spring Data for Apache Geode’s @EnableGemfireCaching annotation, then the above configuration could be simplified to:

Configuring caching using Spring Data Geode. 

@SpringBootApplication
@EnableGemfireCaching
class CachingUsingApacheGeodeConfiguration {

}

And, if you use SBDG, then you only need to do this:

Configuring caching using Spring Data Geode. 

@SpringBootApplication
class CachingUsingApacheGeodeConfiguration {

}

This allows you to focus on the areas in your application that would benefit from caching without having to enable the plumbing. Simply demarcate the service methods in your application that are good candidates for caching:

Using caching in your application. 

@Service
class CustomerService {

  @Caching("CustomersByName")
  Customer findBy(String name) {
    ...
  }
}

[Tip]Tip

Refer to the documentation for more details.

5.5.3 @EnableContinuousQueries

[Note]Note

The ContinuousQueryAutoConfiguration class corresponds to the @EnableContinuousQueries annotation.

Without having to enable anything, you simply annotate your application (POJO) component method(s) with the SDG @ContinuousQuery annotation to register a CQ and start receiving events. The method acts as a CqEvent handler, or in Apache Geode and Pivotal GemFire’s case, the method would be an implementation of CqListener.

Declare application CQs. 

@Component
class MyCustomerApplicationContinuousQueries

  @ContinuousQuery("SELECT customer.* FROM /Customers customers"
    + " WHERE customer.getSentiment().name().equalsIgnoreCase('UNHAPPY')")
  public void handleUnhappyCustomers(CqEvent event) {
    ...
  }
}

As shown above, you define the events you are interested in receiving by using a OQL query with a finely tuned query predicate describing the events of interests and implement the handler method to process the events (e.g. apply a credit to the customer’s account and follow up in email).

[Tip]Tip

Refer to the documentation for more details.

5.5.4 @EnableGemfireFunctionExecutions & @EnableGemfireFunctions

Whether you need to execute a Function or implement a Function, SBDG will detect the Function definition and auto-configure it appropriately for use in your Spring Boot application. You only need to define the Function execution or implementation in a package below the main @SpringBootApplication class.

Declare a Function Execution. 

package example.app.functions;

@OnRegion("Accounts")
interface MyCustomerApplicationFunctions {

    void applyCredit(Customer customer);

}

Then you can inject the Function execution into any application component and use it:

Use the Function. 

package example.app.service;

@Service
interface CustomerService {

    @Autowired
    private MyCustomerapplicationFunctions customerFunctions;

    public void analyzeCustomerSentiment(Customer customer) {

        ...

        this.customerFunctions.applyCredit(customer);

        ...
    }
}

The same pattern basically applies to Function implementations, except in the implementation case, SBDG "registers" the Function implementation for use (i.e. to be called by a Function execution).

The point is, you are simply focusing on defining the logic required by your application, and not worrying about how Functions are registered, called, etc. SBDG is handling this concern for you!

[Note]Note

Function implementations are typically defined and registered on the server-side.

[Tip]Tip

Refer to the documentation for more details.

5.5.5 @EnableGemfireRepositories

[Note]Note

The GemFireRepositoriesAutoConfigurationRegistrar class corresponds to the @EnableGemfireRepositories annotation.

Like Functions, you are only concerned with the data access operations (e.g. basic CRUD and simple Queries) required by your application to carry out its functions, not how to create and perform them (e.g. Region.get(key) & Region.put(key, obj)) or execute (e.g. Query.execute(arguments)).

Simply define your Spring Data Repository:

Define an application-specific Repository. 

package example.app.repo;

interface CustomerRepository extends CrudRepository<Customer, Long> {

  List<Customer> findBySentimentEqualTo(Sentiment sentiment);

}

And use it:

Using the application-specific Repository. 

package example.app.sevice;

@Service
class CustomerService {

  @Autowired
  private CustomerRepository repository;

  public void processCustomersWithSentiment(Sentiment sentiment) {

    this.repository.findBySentimentEqualTo(sentiment).forEach(customer -> { ... });

    ...
  }
}

Your application-specific Repository simply needs to be declared in a package below the main @SpringBootApplication class. Again, you are only focusing on the data access operations and queries required to carry out the functions of your application, nothing more.

[Tip]Tip

Refer to the documentation for more details.

5.5.6 @EnableLogging

[Note]Note

The LoggingAutoConfiguration class corresponds to the @EnableLogging annotation.

Logging is an essential application concern to understand what is happening in the system along with when and where the event occurred. As such, SBDG auto-configures logging for Apache Geode and Pivotal GemFire by default, using the default log-level, "config".

If you wish to change an aspect of logging, such as the log-level, you would typically do this in Spring Boot application.properties:

Change the log-level for Apache Geode. 

# Spring Boot application.properites.

spring.data.gemfire.cache.log-level=debug

Other aspects may be configured as well, such as the log file size and disk space limits for the file system location used to store the Apache Geode log files at runtime.

Under-the-hood, Apache Geode’s logging is based on Log4j. Therefore, you can configure Apache Geode logging using any logging provider (e.g. Logback) and configuration metadata appropriate for that logging provider so long as you supply the necessary adapter between Log4j and whatever logging system you are using. For instance, if you include org.springframework.boot:spring-boot-starter-logging then you will be using Logback and you will need the org.apache.logging.log4j:log4j-to-slf4j adapter.

5.5.7 @EnablePdx

[Note]Note

The PdxSerializationAutoConfiguration class corresponds to the @EnablePdx annotation.

Anytime you need to send an object over the network, overflow or persist an object to disk, then your application domain object must be serializable. It would be painful to have to implement java.io.Serializable in everyone of your application domain objects (e.g. Customer) that would potentially need to be serialized.

Furthermore, using Java Serialization may not be ideal (e.g. the most portable or efficient) in all cases, or even possible in other cases (e.g. when you are using a 3rd party library for which you have no control over).

In these situations, you need to be able to send your object anywhere without unduly requiring the class type to be serializable as well as to exist on the classpath for every place it is sent. Indeed, the final destination may not even be a Java application! This is where Apache Geode PDX Serialization steps into help.

However, you don’t have to figure out how to configure PDX to identify the application class types that will need to be serialized. You simply define your class type:

Customer class. 

@Region("Customers")
class Customer {

  @Id
  private Long id;

  @Indexed
  private String name;

  ...
}

And, SBDG’s Auto-configuration will handle the rest!

[Tip]Tip

Refer to the documentation for more details.

5.5.8 @EnableSecurity

[Note]Note

The ClientSecurityAutoConfiguration class and PeerSecurityAutoConfiguration class corresponds to the @EnableSecurity annotation, but applies Security, and specifically, Authentication/Authorization configuration for both clients and servers.

Configuring your Spring Boot, Apache Geode ClientCache application to properly authenticate with a cluster of secure Apache Geode or Pivotal GemFire servers is as simple as setting a username and password in Spring Boot application.properties:

Supplying Authentication Credentials. 

# Spring Boot application.properties

spring.data.gemfire.security.username=Batman
spring.data.gemfire.security.password=r0b!n5ucks

[Note]Note

Authentication is even easier to configure in a managed environment like PCF when using PCC; you don’t have to do anything!

Authorization is configured on the server-side and is made simple with SBDG and the help of Apache Shiro. Of course, this assumes you are using SBDG to configure and bootstrap your Apache Geode cluster in the first place, which is possible, and made even easier with SBDG.

[Tip]Tip

Refer to the documentation for more details.

5.5.9 @EnableSsl

[Note]Note

The SslAutoConfiguration class corresponds to the @EnableSsl annotation.

Configuring SSL for secure transport (TLS) between your Spring Boot, Apache Geode ClientCache application and the cluster can be a real problematic task, especially to get correct from the start. So, it is something that SBDG makes simple to do out-of-the-box.

Simply supply a trusted.keystore file containing the certificates in a well-known location (e.g. root of your application classpath) and SBDG’s Auto-configuration will kick in and handle of the rest.

This is useful during development, but we highly recommend using a more secure procedure (e.g. integrating with a secure credential store like LDAP, CredHub or Vault) when deploying your Spring Boot application to production.

[Tip]Tip

Refer to the documentation for more details.

5.5.10 @EnableGemFireHttpSession

[Note]Note

The SpringSessionAutoConfiguration class corresponds to the @EnableSsl annotation.

Configuring Apache Geode or Pivotal GemFire to serve as the (HTTP) Session state caching provider using Spring Session is as simple as including the correct starter, e.g. spring-geode-starter-session.

Using Spring Session. 

<dependency>
    <groupId>org.springframework.geode</groupId>
    <artifactId>spring-geode-starter-session</artifactId>
    <version>1.3.0.M2</version>
</dependency>

With Spring Session, and specifically Spring Session for Apache Geode or Pivotal GemFire (SSDG), on the classpath of your Spring Boot, Apache Geode ClientCache Web application, you can manage your (HTTP) Session state with either Apache Geode or Pivotal GemFire. No further configuration is needed. SBDG Auto-configuration detects Spring Session on the application classpath and does the right thing.

[Tip]Tip

Refer to the documentation for more details.

5.5.11 RegionTemplateAutoConfiguration

The SBDG RegionTemplateAutoConfiguration class has no corresponding SDG Annotation. However, the Auto-configuration of a GemfireTemplate for every single Apache Geode Region defined and declared in your Spring Boot application is supplied by SBDG never-the-less.

For example, if you defined a Region using:

Region definition using JavaConfig. 

@Configuration
class GeodeConfiguration {


  @Bean("Customers")
  ClientRegionFactoryBean<Long, Customer> customersRegion(GemFireCache cache) {

    ClientRegionFactoryBean<Long, Customer> customersRegion =
      new ClientRegionFactoryBean<>();

    customersRegion.setCache(cache);
    customersRegion.setShortcut(ClientRegionShortcut.PROXY);

    return customersRegion;
  }
}

Alternatively, you could define the "Customers" Region using:

Region definition using @EnableEntityDefinedRegions

@Configuration
@EnableEntityDefinedRegion(basePackageClasses = Customer.class)
class GeodeConfiguration {

}

Then, SBDG will supply a GemfireTemplate instance that you can use to perform low-level, data access operations (indirectly) on the "Customers" Region:

Use the GemfireTemplate to access the "Customers" Region. 

@Repository
class CustomersDao {

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

  Customer findById(Long id) {
    return this.customerTemplate.get(id);
  }
}

You do not need to explicitly configure GemfireTemplates for each Region you need to have low-level data access to (e.g. such as when you are not using the Spring Data Repository abstraction).

Be careful to "qualify" the GemfireTemplate for the Region you need data access to, especially given that you will probably have more than 1 Region defined in your Spring Boot application.

[Tip]Tip

Refer to the documentation for more details.