This topic explains how to build a Spring Boot application configured with Spring Session for VMware Tanzu GemFire to transparently leverage VMware Tanzu GemFire to manage a web application’s javax.servlet.http.HttpSession.

In this sample, the Tanzu GemFire Client-Server topology is employed using a pair of Spring Boot applications, one to configure and run a Tanzu GemFire Server and another to configure and run the cache client, a Spring MVC-based web application making use of the HttpSession.

Updating Dependencies

Before using Spring Session, you must ensure that the required dependencies are included. If you are using Maven, include the following dependencies in your pom.xml:

<dependencies>

    <!-- ... -->
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-3.0-gemfire-10.0</artifactId>
        <version> 1.0.0</version>
        <type>pom</type>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

</dependencies>

Spring Boot Configuration

After adding the required dependencies and repository declarations, we can create the Spring configuration for our Tanzu GemFire client using Spring Boot. The Spring configuration is responsible for creating a Servlet Filter that replaces the Web container’s HttpSession with an implementation backed by Spring Session, which is then stored and managed in Tanzu GemFire.

Spring Boot, Tanzu GemFire Cache Server

We start with a Spring Boot application to configure and bootstrap the Tanzu GemFire Server:

@SpringBootApplication //SEE COMMENT 1
@CacheServerApplication(name = "SpringSessionDataGemFireBootSampleServer", logLevel = "error") //SEE COMMENT 2
@EnableGemFireHttpSession(maxInactiveIntervalInSeconds = 20) //SEE COMMENT 3
public class GemFireServer {

    public static void main(String[] args) {

        new SpringApplicationBuilder(GemFireServer.class)
            .web(WebApplicationType.NONE)
            .build()
            .run(args);
    }
}

Comments:

  1. We annotate the Tanzu GemFire Server configuration class, GemFireServer, with @SpringBootApplication to indicate that this is a Spring Boot application leveraging all of Spring Boot’s features.

  2. We use the Spring Data for Tanzu GemFire configuration annotation @CacheServerApplication to simplify the creation of a peer cache instance containing a CacheServer for cache clients to connect.

  3. (Optional) We use the @EnableGemFireHttpSession annotation to create the necessary server-side Region (by default, ClusteredSpringSessions) to store the HttpSessions state. This step is optional because the Session Region can be created manually.

Spring Boot, Tanzu GemFire Cache Client Web Application

We create a Spring Boot Web application to expose our Web service with Spring Web MVC, running as an Tanzu GemFire cache client connected to our Spring Boot, Tanzu GemFire Server. The Web application will use Spring Session backed by Tanzu GemFire to manage HttpSession state in a clustered (distributed) and replicated manner.

@SpringBootApplication //SEE COMMENT 1
@Controller //SEE COMMENT 2
public class Application {

    static final String INDEX_TEMPLATE_VIEW_NAME = "index";
    static final String PING_RESPONSE = "PONG";
    static final String REQUEST_COUNT_ATTRIBUTE_NAME = "requestCount";

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

    @ClientCacheApplication(name = "SpringSessionDataGemFireBootSampleClient", logLevel = "error",
        readTimeout = 15000, retryAttempts = 1, subscriptionEnabled = true) //SEE COMMENT 3
    @EnableGemFireHttpSession(poolName = "DEFAULT") //SEE COMMENT 4
    static class ClientCacheConfiguration extends ClientServerIntegrationTestsSupport {

        @Bean
        ClientCacheConfigurer gemfireServerReadyConfigurer( //SEE COMMENT 5
            @Value("${spring.data.gemfire.cache.server.port:40404}") int cacheServerPort) {

            return (beanName, clientCacheFactoryBean) -> waitForServerToStart("localhost", cacheServerPort);
        }
    }

    @Configuration
    static class SpringWebMvcConfiguration { //SEE COMMENT 6

        @Bean
        public WebMvcConfigurer webMvcConfig() {

            return new WebMvcConfigurer() {

                @Override
                public void addViewControllers(ViewControllerRegistry registry) {
                    registry.addViewController("/").setViewName(INDEX_TEMPLATE_VIEW_NAME);
                }
            };
        }
    }

    @ExceptionHandler
    @ResponseBody
    public String errorHandler(Throwable error) {
        StringWriter writer = new StringWriter();
        error.printStackTrace(new PrintWriter(writer));
        return writer.toString();
    }

    @RequestMapping(method = RequestMethod.GET, path = "/ping")
    @ResponseBody
    public String ping() {
        return PING_RESPONSE;
    }

    @RequestMapping(method = RequestMethod.POST, path = "/session")
    public String session(HttpSession session, ModelMap modelMap,
        @RequestParam(name = "attributeName", required = false) String name,
        @RequestParam(name = "attributeValue", required = false) String value) { //SEE COMMENT 7

        modelMap.addAttribute("sessionAttributes",
            attributes(setAttribute(updateRequestCount(session), name, value)));

        return INDEX_TEMPLATE_VIEW_NAME;
    }
}

Comments:

  1. We declare our Web application to be a Spring Boot application by annotating our application class with @SpringBootApplication.

  2. @Controller is a Spring Web MVC annotation enabling our MVC handler mapping methods (i.e. methods annotated with @RequestMapping) to process HTTP requests, for example <7>.

  3. We declare our Web application to be an Tanzu GemFire cache client by annotating our application class with @ClientCacheApplication. Additionally, we adjust a few basic, “DEFAULT” Pool settings, for example readTimeout.

  4. We declare that the Web application will use Spring Session backed by Tanzu GemFire by annotating the ClientCacheConfiguration class with @EnableGemFireHttpSession. This will create the necessary client-side Region (by default, “ClusteredSpringSessions” as a PROXY Region) corresponding to the same server-side Region by name. All HttpSession state will be sent from the cache client Web application to the server through Region data access operations. The client-side Region uses the “DEFAULT” Pool.

  5. We wait to ensure the Tanzu GemFire Server is up and running before we proceed. This is used for automated integration testing purposes.

  6. We adjust the Spring Web MVC configuration to set the home page.

  7. We declare the /sessions HTTP request handler method to set an HTTP Session attribute and increment a count for the number of HTTP requests.

Many other useful utility methods exist. Refer to the actual source code for full details.

Note: In typical Tanzu GemFire production deployments, where the cluster includes potentially hundreds or thousands of servers (data nodes), it is more common for clients to connect to one or more Tanzu GemFire Locators running in the same cluster. A Locator passes meta-data to clients about the servers available in the cluster, the individual server load, and which servers have the client's data of interest, which is particularly important for direct, single-hop data access and latency-sensitive applications. For more information, see Standard Client-Server Deployment in the Tanzu GemFire product documentation.

For more information about configuring Spring Data for VMware Tanzu GemFire, see Spring Data for VMware Tanzu GemFire Reference Guide in the Spring product documentation.

Enabling HttpSession Management

The @EnableGemFireHttpSession annotation enables developers to configure certain aspects of both Spring Session and Tanzu GemFire out-of-the-box using the following attributes:

  • clientRegionShortcut: Configures the data management policy on the client using the ClientRegionShortcut (see VMware GemFire Java API Reference). Defaults to PROXY. Only applicable on the client.

  • indexableSessionAttributes: Identifies the HttpSession attributes by name that should be indexed for queries. Only Session attributes explicitly identified by name will be indexed.

  • maxInactiveIntervalInSeconds:Controls HttpSession Idle Expiration Timeout (TTI; defaults to 30 minutes).

  • poolName: Name of the dedicated connection Pool connecting the client to a cluster of servers. Defaults to gemfirePool. Only applicable on the client.

  • regionName: Declares the name of the Region used to store and manage HttpSession state. Defaults to “ClusteredSpringSessions”.

  • serverRegionShortcut: Configures the data management policy on the client using the RegionShortcut (see VMware GemFire Java API Reference). Defaults to PARTITION. Only applicable on the server, or when the P2P topology is employed.

Note: The Tanzu GemFire client Region name must match a server Region by the same name if the client Region is a PROXY or CACHING_PROXY. Client and server Region names are not required to match if the client Region is LOCAL. However, by using a client LOCAL Region, HttpSession state will not be propagated to the server and you lose all the benefits of using Tanzu GemFire to store and manage HttpSession state on the servers in a distributed, replicated manner.

Spring Boot Sample Web Application

The following is a sample Spring Boot web application with a Tanzu GemFire-Managed HttpSession.

Running the Boot Sample Application

To run the sample app:

  1. Obtain the source code.

  2. In a terminal window, run the server:

    ./gradlew :spring-session-sample-boot-gemfire:run
    
  3. In a separate terminal window, run the client:

    ./gradlew :spring-session-sample-boot-gemfire:bootRun
    
  4. In a browser, access the application at http://localhost:8080/.

In this sample, the Web application is the Spring Boot, Tanzu GemFire cache client and the server is standalone, separate JVM process.

Exploring the Sample Application

  1. In the application, complete the form with the following information:

    • Attribute Name: username
    • Attribute Value: test
  2. Click the Set Attribute button. You should see the attribute name and value displayed in the table along with an additional attribute, requestCount, which shows the number of HTTP requests made.

How the Application Works

We interact with the standard javax.servlet.http.HttpSession in the Spring Web MVC service endpoint, located in src/main/java/sample/client/Application.java.

@Controller
class SessionController {

    @RequestMapping(method = RequestMethod.POST, path = "/session")
    public String session(HttpSession session, ModelMap modelMap,
        @RequestParam(name = "attributeName", required = false) String name,
        @RequestParam(name = "attributeValue", required = false) String value) {

        modelMap.addAttribute("sessionAttributes",
            attributes(setAttribute(updateRequestCount(session), name, value)));

        return INDEX_TEMPLATE_VIEW_NAME;
    }
}

Instead of using the embedded HTTP server’s HttpSession, we persist the Session state in Tanzu GemFire. Spring Session creates a cookie named “SESSION” in your browser that contains the ID of the Session. You can view the cookies using your browser controls.

check-circle-line exclamation-circle-line close-line
Scroll to top icon