Spring Boot for Tanzu GemFire 1.0

Docker

Last Updated February 19, 2025

This topic discusses using Docker with Spring Boot for VMware Tanzu GemFire.

The state of modern software application development is moving towards containerization. Containers offer a controlled environment to predictably build (compile, configure and package), run, and manage your applications in a reliable and repeatable manner, regardless of context. In many situations, the intrinsic benefit of using containers is obvious.

Understandably, Docker’s popularity took off like wildfire, given its highly powerful and simplified model for creating, using and managing containers to run packaged applications.

Docker’s ecosystem is also impressive, with the advent of Testcontainers and Spring Boot’s dedicated support to create packaged Spring Boot applications in Docker images that are then later run in a Docker container.

Tip See also Deploying to Containers to learn more.

VMware GemFire can also run in a controlled, containerized environment. The goal of this chapter is to get you started running VMware GemFire in a container and interfacing to a containerized VMware GemFire cluster from your Spring Boot, VMware GemFire client applications.

This chapter does not cover how to run your Spring Boot, VMware GemFire client applications in a container, since that is already covered by Spring Boot (see the Spring Boot documentation for Docker images and container deployment, along with Docker’s documentation). Instead, our focus is on how to connect to a VMware GemFire cluster in a container from a Spring Boot, VMware GemFire client application, regardless of whether the application runs in a container or not.

First, set up your containerized VMware GemFire cluster and make sure to map ports between the Docker container and the host system, exposing well-known ports used by VMware GemFire server-side cluster processes, such as Locators and CacheServers:

Table 1. VMware GemFire Ports
Process Port

HTTP

7070

Locator

10334

Manager

1099

Server

40404

Table 1. VMware GemFire Ports

Spring Boot, VMware GemFire Client Application Explained

The Spring Boot, VMware GemFire ClientCache application we use to connect to our VMware GemFire cluster that runs in the Docker container appears as follows:

Example 5. Spring Boot, VMware GemFire Docker client application

@SpringBootApplication
@EnableClusterAware
@EnableEntityDefinedRegions(basePackageClasses = Customer.class)
@UseMemberName("SpringBootGemFireDockerClientCacheApplication")
public class SpringBootGemFireDockerClientCacheApplication {

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

    @Bean
    @SuppressWarnings("unused")
    ApplicationRunner runner(GemFireCache cache, CustomerRepository customerRepository) {

        return args -> {

            assertClientCacheAndConfigureMappingPdxSerializer(cache);
            assertThat(customerRepository.count()).isEqualTo(0);

            Customer jonDoe = Customer.newCustomer(1L, "Jon Doe");

            log("Saving Customer [%s]...%n", jonDoe);

            jonDoe = customerRepository.save(jonDoe);

            assertThat(jonDoe).isNotNull();
            assertThat(jonDoe.getId()).isEqualTo(1L);
            assertThat(jonDoe.getName()).isEqualTo("Jon Doe");
            assertThat(customerRepository.count()).isEqualTo(1);

            log("Querying for Customer [SELECT * FROM /Customers WHERE name LIKE '%s']...%n", "%Doe");

            Customer queriedJonDoe = customerRepository.findByNameLike("%Doe");

            assertThat(queriedJonDoe).isEqualTo(jonDoe);

            log("Customer was [%s]%n", queriedJonDoe);
        };
    }

    private void assertClientCacheAndConfigureMappingPdxSerializer(GemFireCache cache) {

        assertThat(cache).isNotNull();
        assertThat(cache.getName())
            .isEqualTo(SpringBootGemFireDockerClientCacheApplication.class.getSimpleName());
        assertThat(cache.getPdxSerializer()).isInstanceOf(MappingPdxSerializer.class);

        MappingPdxSerializer serializer = (MappingPdxSerializer) cache.getPdxSerializer();

        serializer.setIncludeTypeFilters(type -> Optional.ofNullable(type)
            .map(Class::getPackage)
            .map(Package::getName)
            .filter(packageName -> packageName.startsWith(this.getClass().getPackage().getName()))
            .isPresent());
    }

    private void log(String message, Object... args) {
        System.err.printf(message, args);
        System.err.flush();
    }
}

Our Customer application domain model object type is defined as:

Example 6. Customer class

@Region("Customers")
class Customer {

    @Id
    private Long id;

    private String name;

}

Also, we define a Spring Data CRUD Repository to persist and access Customers stored in the /Customers Region:

Example 7. CustomerRepository interface

interface CustomerRepository extends CrudRepository<Customer, Long> {

    Customer findByNameLike(String name);

}

Our main class is annotated with @SpringBootApplication, making it be a proper Spring Boot application.

We additionally annotate the main class with Spring Boot for Tanzu GemFire’s @EnableClusterAware annotation to automatically detect the VMware GemFire cluster that runs in the Docker container and to push cluster configuration metadata from the application to the cluster as required by the application.

Specifically, the application requires that a Region called “Customers”, as defined by the @Region mapping annotation on the Customer application domain model class, exists on the servers in the cluster, to store Customer data.

We use the Spring Data for VMware GemFire @EnableEntityDefinedRegions annotation to define the matching client PROXY “Customers” Region.

Optionally, we have also annotated our main class with Spring Boot for Tanzu GemFire’s @UseMemberName annotation to give the ClientCache a name, which we assert in the assertClientCacheAndConfigureMappingPdxSerializer(:ClientCache) method.

The primary work performed by this application is done in the Spring Boot ApplicationRunner bean definition. We create a Customer instance (Jon Doe), save it to the “Customers” Region that is managed by the server in the cluster, and then query for Jon Doe using OQL, asserting that the result is equal to what we expect.

We log the output from the application’s operations to see the application in action.

Running the Spring Boot, VMware GemFire client application

When you run the Spring Boot, VMware GemFire client application, you should see output similar to the following:

Example 8. Application log output

/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/java ...
    org.springframework.geode.docs.example.app.docker.SpringBootGemFireDockerClientCacheApplication

  .   ____          _            __ _ _
 /\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.3.0.RELEASE)

Saving Customer [Customer(name=Jon Doe)]...
Querying for Customer [SELECT * FROM /Customers WHERE name LIKE '%Doe']...
Customer was [Customer(name=Jon Doe)]

Process finished with exit code 0

When we review the configuration of the cluster, we see that the /Customers Region was created when the application ran:

Example 9. /Customers Region Configuration

gfsh>list regions
List of regions
---------------
Customers


gfsh>describe region --name=/Customers
Name            : Customers
Data Policy     : partition
Hosting Members : ServerOne

Non-Default Attributes Shared By Hosting Members

 Type  |    Name     | Value
------ | ----------- | ---------
Region | size        | 1
       | data-policy | PARTITION

Our /Customers Region contains a value (Jon Doe), and we can verify this by running the following OQL Query with gfsh:

Example 10. Query the /Customers Region

gfsh>query --query="SELECT customer.name FROM /Customers customer"
Result : true
Limit  : 100
Rows   : 1

Result
-------
Jon Doe

Our application ran successfully.

Conclusion

In this chapter, we saw how to connect a Spring Boot, VMware GemFire ClientCache application to an VMware GemFire cluster that runs in a Docker container.

Later, we provide more information on how to scale up, or rather scale out, our VMware GemFire cluster that runs in Docker. Additionally, we provide details on how you can use VMware GemFire’s Docker image with Testcontainers when you write integration tests.