This article aims to provide a step by step guide for setting up a remote Red Hat JBoss Data Grid (JDG) cluster as an HTTP session store for your state-full web applications running on Red Hat JBoss Enterprise Application Platform (EAP). I had recently explored this setup for another customer and figured it would be helpful to put together a set of detailed instructions for replicating this. This feature was recently released with the GA of JDG 6.5.

Benefits of this Solution

Here are some of the reasons why you might want to consider this solution:

  1. Increased application scalability and elasticity. By offloading the session data off to a remote Data Grid, the application tier itself can be more scalable and elastic. Adding a new EAP instance to the cluster will not require a rehash process which could be problematic especially when we are dealing with a lot of session data.
  2. Session Persistence. By offloading session data to a remote data grid, the application itself will be able to survive EAP node failures since the a JVM failure will not cause the session data to be lost. In addition, additional cache persistence policies can be set up on the remote data grid so the session data is persisted to a user defined persistence medium.
  3. Session Data Sharing. If you have a requirement for multiple applications to be able to share session data, this solution might be able to solve that use case as well.

Detailed Configuration

Configuring JBoss EAP Cluster

First we need to configure the Infinispan subsystem of the EAP server(s) to write session data to the remote JDG cluster. In order to do this, we will execute a set of EAP Command Line Interface (CLI) commands to configure the underlying cache container to preform this remote write of the Http Session data. All these commands can also be batched up and executed as a script they are going to be executed individually in this example.

  1. Create a new Cache Container which is going to be holding the definition for the session data cache.
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container:add(default-cache=remote-http-cache,
  2. Create a remote cache inside the parent cache container. This is going to be referenced from the web application to externalize the session data.
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container/distributed-cache=remote-http-cache:add(mode=ASYNC, batching=true)
  3. Add a new transport setting
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container/transport=TRANSPORT:add(lock-timeout=60000)
  4. Define the remote Data Grid cluster to persist the session data
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container/distributed-cache=remote-http-cache/remote-store=REMOTE_STORE:add(remote-servers=[{"outbound-socket-binding" => "remote-jdg-server1"}])
  5. Set the properties for the remote cache store:
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container/distributed-cache=remote-http-cache/remote-store=REMOTE_STORE:write-attribute(name=cache, value=remote-http-cache)
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container/distributed-cache=remote-http-cache/remote-store=REMOTE_STORE:write-attribute(name=socket-timeout, value=60000)
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container/distributed-cache=remote-http-cache/remote-store=REMOTE_STORE:write-attribute(name=shared, value=true)
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container/distributed-cache=remote-http-cache/remote-store=REMOTE_STORE:write-attribute(name=passivation, value=false)
    [standalone@localhost:9999 /] /subsystem=infinispan/cache-container=remote-http-container/distributed-cache=remote-http-cache/remote-store=REMOTE_STORE:write-attribute(name=purge, value=false)
  6. Define the Socket Binding profile with the actual address for the remote JDG servers
    [standalone@localhost:9999 /] /socket-binding-group=standard-sockets/remote-destination-outbound-socket-binding=remote-jdg-server1:add(host=localhost,port=11222)

Configuring JBoss JDG Cluster

  1. Create a new cache store on the remote Data Grid Cluster to define the external cache that we are going to be persisting our session data to.
    [standalone@localhost:9999 cache-container=clustered] ./distributed-cache=remote-http-cache:add(mode=SYNC, start=EAGER)
    {"outcome" => "success"}
  2. You should also see the following confirmation on your JDG console
    INFO  [] (MSC service thread 1-7) JBAS010281: Started remote-http-cache cache from clustered container

Now we are ready to test this solution!

Verifying the Setup

In order to verify this configuration, we first need a state full web application that is going persist data into the HttpSession object.

You can access a sample stateful application from here.

    1. Deploy the above application into a JBoss EAP Cluster.
    2. You should notice that the application is not configured to write the session data to the remote JDG cluster. We need to make an update to the jboss-web.xml to define the cache-name for the session replication configuration.
      <?xml version="1.0" encoding="UTF-8"?>
    3. Access the application from one of the servers where it is deployed to. You should notice that the counter will increase.
    4. Now use the JDG cli to connect to the remote JDG server to verify that the session information has indeed been written to the data grid cluster.
      [standalone@localhost:9999 cache-container=clustered]  cd /subsystem=infinispan/cache-container=clustered/distributed-cache=remote-http-cache
      [standalone@localhost:9999 distributed-cache=remote-http-cache] stats
      Statistics: {
        removeHits: 0
        stores: 3
        numberOfEntries: 1
        hitRatio: 0.0
        removeMisses: 0
        averageRemoveTime: 0
        elapsedTime: 1060
        evictions: 0
        hits: 0
        misses: 8
        statisticsEnabled: true
        averageWriteTime: 0
        readWriteRatio: 2.6666666666666665
        averageReadTime: 0
        timeSinceReset: 1060

The session data has been externalized successfully! You can also test the persistent aspect of this solution by shutting down the EAP server and then bring it back and access the application with the previous session id - this time EAP should be able to use the session id and query the cache for the session data and pick up from where it left off.