Tomcat Session State Caching

Enable Session State Caching

By default, the Tomcat instance is configured to store all sessions and their data in memory. Under certain circumstances it may be appropriate to persist the sessions and their data to a repository. When this is the case (small amounts of data that should survive the failure of any individual instance), the buildpack can automatically configure Tomcat to do so by binding an appropriate service. In this case, the service is Pivotal Cloud Cache.

When the session-replication tag is specified, the sessions will be stored in the Pivotal Cloud Cache service instance, thus moving the data out of Tomcat. An application bound to this service will start running in a Tomcat instance. A region for storing sessions will be created. The region will be named gemfire_modules_sessions. A 30-minute expiration for sessions will be automatically configured.

For session state caching, use a version 4.3 or more recent Java buildpack.

To enable Tomcat session state caching, do one of these options:

  • Option 1: When creating your service instance name, specify the session-replication tag. For example:

     $ cf create-service p-cloudcache small-plan my-service-instance -t session-replication
  • Option 2: Update your service instance, specifying the session-replication tag:

    $ cf update-service new-service-instance -t session-replication
  • Option 3: When creating the service, include the substring session-replication anywhere within the service instance name. An example with the substring is my-service-instance-session-replication.

Do not mix Tomcat session state caching (as described here) with Spring Session caching as described in Spring Session Caching. Mixing the two is problematic.

Java Buildpack Version Incompatibility

The Cloud Foundry Java buildpack specifies a Geode Tomcat Session Store that corresponds to your Pivotal Cloud Cache version. If your version of the Cloud Foundry Java buildpack specifies a geode_store version that is more recent than your tile’s version of Pivotal Cloud Cache, you will need to specify a different version of Pivotal Cloud Cache than is provided by the Java buildpack. The complete list of geode_store versions is given in https://java-buildpack-tomcat-gemfire-store.s3-us-west-2.amazonaws.com/index.yml.

There are three ways to specify and/or use a different buildpack. Choose and implement one of these three ways.

  • Replace the Tanzu Application Service (TAS) environment’s Java buildpack.

    1. After a cf login targeting the correct org and space, delete the current TAS environment’s offline Java buildpack:

      cf delete-buildpack java_buildpack_offline
      
    2. Download the replacement Java buildpack (offline) from Tanzu Network.

    3. Upload the replacement Java buildpack (offline) to your TAS environment. This example specifies a version 4.37 buildpack:

      cf create-buildpack java_buildpack_offline /PATH/TO/java-buildpack-offline-v4.37.zip POSITION
      

      where POSITION is the order in which this buildpack will be selected.

  • Specify both a geode_store version environment variable and an online buildpack for your application. Each of these can be accomplished in either of two ways.

    • Specify a geode_store version environment variable in one of two ways:

      • Set the geode_store version environment variable in your application’s manifest.yml file. For details on how to specify configuration values through environment variable in the Java Buildpack, see Cloud Foundry Java Buildpack. You can find the buildpack’s geode_store version in file /config/tomcat.yml. For example:
      env:
        JBP_CONFIG_TOMCAT: '{ geode_store: { version: 1.12.0 } }'
      
      • Set the geode_store version environment variable with the cf set-env command.
    • Specify an online buildpack in one of two ways:

      • Specify an online buildpack in your application’s manifest.yml file, as in the example:
      buildpacks:
        - https://github.com/cloudfoundry/java-buildpack.git#v4.37
      
      • Specify an online buildpack in the cf push of your application.
  • Create a custom buildpack which specifies the version as described in Create a Custom Buildpack.

Tomcat Versions Incompatibility

This Tomcat session state caching warning issued during app deployment may indicate a version incompatibility:

WARNING: Tomcat version X does not match Geode Tomcat Y module. If you
encounter compatibility issues, please make sure these versions match.

This warning indicates an issue that needs to be addressed if your version of Tomcat is significantly older (such as a Tomcat version prior to version 8) than the current default Tomcat version specifications.

You can fix this warning by changing the version of Tomcat being used by the Java buildpack in one of two ways:

  • Create a Custom Buildpack and modify the version of Tomcat in your custom buildpack.

  • Specify the online buildpack in the app’s manifest.yml file, and set an environment variable in the app’s manifest.yml file as described in Cloud Foundry Java Buildpack Configuration and Extension. For example:

    buildpacks:
      - https://github.com/cloudfoundry/java-buildpack.git#v4.37
    env:
      JBP_CONFIG_TOMCAT: '{ tomcat: { version: 9.0.+ } }'
    

    For a full list of environment variables related to configuring Tomcat in the Java buildpack, see Tomcat Container Configuration.

Disable Near Caching Within the App

Near caching is when an app locally caches data. Near caching uses an embedded cache within the app. Web apps that deploy Tomcat with session state caching have near caching by default. To keep an app stateless, you will want to disable near caching.

If you are not using an external repository for configuration, Create a Custom Buildpack to disable near caching.

Create a Custom Buildpack

If your Pivotal Cloud Cache version is not compatible with the dependencies included in the Java buildpack, you can create a custom buildpack.

  1. Clone the Cloud Foundry Java buildpack repository:

    $ git clone git@github.com:cloudfoundry/java-buildpack.git
    
  2. Change directories to the newly-created repository clone:

    $ cd java-buildpack
    
  3. Check out the desired version or release of the java-buildpack repository on a local branch. Use v4.36 or the most recent version available.

  4. To change the version of Pivotal Cloud Cache used by the buildpack, edit the /config/tomcat.yml configuration file to specify the geode_store. Here is the portion of the file to be changed, with the string to change in bold:

    geode_store:
      version: 1.13.+
      repository_root: https://java-buildpack-tomcat-gemfire-store.s3-us-west-2.amazonaws.com
    

    Change the geode_store version to 1.12.0 for Pivotal Cloud Cache version 1.12.

    Change the geode_store version to 1.11.0 for Pivotal Cloud Cache version 1.11.

    Change the geode_store version to 0.0.2 for all previous Pivotal Cloud Cache versions. The complete list of geode_store versions is given in https://java-buildpack-tomcat-gemfire-store.s3-us-west-2.amazonaws.com/index.yml.

  5. If you changed the version of Pivotal Cloud Cache used by the buildpack, you may also need to change the version of the Geode Session State Module used by the buildpack. Edit the following line in the java-buildpack repository file lib/java_buildpack/container/tomcat/tomcat_geode_store.rb to specify the appropriate version of Tomcat for your current geode_store version:

    SESSION_MANAGER_CLASS_NAME = 'org.apache.geode.modules.session.catalina.Tomcat9DeltaSessionManager'
    

    For versions of geode_store that are 1.11 or greater, use Tomcat9DeltaSessionManager. For versions of geode_store previous to 1.11 and those with geode_store version 0.0.2, use Tomcat8DeltaSessionManager.

  6. To disable near caching within the custom buildpack, edit the java-buildpack repository file lib/java_buildpack/container/tomcat/tomcat_geode_store.rb such that it disables caching within the app. Change the string true to instead be false. Before the change, here is the portion of the file to be changed, with the string to change highlighted:

    def add_manager(context)
      context.add_element 'Manager',
                          'className' => SESSION_MANAGER_CLASS_NAME,
                          'enableLocalCache' => 'true',
                          'regionAttributesId' => REGION_ATTRIBUTES_ID
    end
    

    After changing the highlighted string from true to false, here is the portion of the file with the change highlighted:

    def add_manager(context)
      context.add_element 'Manager',
                          'className' => SESSION_MANAGER_CLASS_NAME,
                          'enableLocalCache' => 'false',
                          'regionAttributesId' => REGION_ATTRIBUTES_ID
    end
    
  7. Commit the changes to your local branch.

  8. Create your custom Java buildpack on the platform with a command of the form:

    cf create-buildpack BUILDPACK-NAME PATH POSITION
    

    where BUILDPACK-NAME is the name you choose for your buildpack, PATH is the location of your local Java buildpack directory, and POSITION is the order in which your buildpack will be selected.

  9. After building your application, push it such that it uses your buildpack:

    cf push -f ./manifest.yml -b BUILDPACK-NAME
    

    where BUILDPACK-NAME is the name you chose for your buildpack.

  10. Bind your app as described in Bind an App to a Service Instance.

  11. Restage the app to ensure proper configuration:

    cf restage APP-NAME
    

    where APP-NAME is the name you chose for app.

Use an External Repository for Configuration

The Tomcat container can be customized if you place the custom configuration in a repository. Using an external repository for configuration also facilitates having a single configuration that may be used by a variety of apps.

There are two parts to using an external repository:

  • Part 1: Build a repository to hold the configuration, and then push the repository to the space, such that the app will have access.
  • Part 2: Change the app such that it uses the external repository.

Part 1 builds the repository:

  1. Make a directory to hold the configuration:

    $ mkdir tomcat-config
    
  2. Make other needed files and directories within the newly created directory:

    $ cd tomcat-config
    $ mkdir public
    $ mkdir -p tomcat-1.0.0/conf
    $ touch Staticfile
    
  3. Edit Staticfile to contain:

    root: public
    directory: visible
    
  4. Create a tomcat-1.0.0/conf/context.xml file. This example content specifies Tomcat version 9 and disables near caching:

    <?xml version='1.0' encoding='UTF-8'?>
    <!--
    ~ Copyright 2013-2019 the original author or authors.
    ~
    ~ Licensed under the Apache License, Version 2.0 (the "License");
    ~ you may not use this file except in compliance with the License.
    ~ You may obtain a copy of the License at
    ~
    ~      http://www.apache.org/licenses/LICENSE-2.0
    ~
    ~ Unless required by applicable law or agreed to in writing, software
    ~ distributed under the License is distributed on an "AS IS" BASIS,
    ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    ~ See the License for the specific language governing permissions and
    ~ limitations under the License.
    -->
    <Context>
        <Resources allowLinking='true'/>
        <Manager className='org.apache.geode.modules.session.catalina.Tomcat9DeltaSessionManager' enableLocalCache='false' regionAttributesId='PARTITION_REDUNDANT_HEAP_LRU'/>
    </Context>
    

    You can customize Tomcat further by placing custom configuration files within the tomcat-1.0.0/conf directory.

  5. Place a compressed TAR format version of the tomcat-1.0.0 directory into the public directory:

    $ tar -czf tomcat-1.0.0.tar.gz tomcat-1.0.0/
    $ cp tomcat-1.0.0.tar.gz public/
    
  6. With a current working directory of tomcat-config, use cf push to place the configuration into the Tanzu Application Service for VMs space that will host the app:

    $ cf push tomcat-config
    
  7. Issue the command

    $ cf apps
    

    to acquire the URL of the tomcat-config app. Prepend the listed URL with http:// to have the URL that will identify the location of the configuration needed by the app.

    For example, your complete URL will look something like http://tomcat-config.apps.yellow-green.cf-app.com.

  8. Within the tomcat-config directory, edit public/index.yml to have URL-specific contents. Using the example URL as a guide, the contents of this public/index.yml file will contain:

    ---
    1.0.0: http://tomcat-config.apps.yellow-green.cf-app.com/tomcat-1.0.0.tar.gz
    
    
  9. Push the configuration a second time with its completed configuration:

    cf push tomcat-config
    

Part 2 modifies the app to configure the use of the external repository:

  1. Edit the manifest.yml file by appending this URL-specific configuration to the applications section of the manifest.yml file:

      env:
        JBP_CONFIG_TOMCAT: "{ tomcat: { external_configuration_enabled: true }, external_configuration: { repository_root: "http://tomcat-config.apps.yellow-green.cf-app.com" } }"
    

    Substitute your complete URL for the URL in this example.

    A complete manifest.yml file will appear similar to:

    ---
    applications:
    - name: http-session-caching
      path: build/libs/http-session-caching-0.0.1.war
      buildpack: java_buildpack_offline
      env:
        JBP_CONFIG_TOMCAT: "{ tomcat: { external_configuration_enabled: true }, external_configuration: { repository_root: "http://tomcat-config.apps.yellow-green.cf-app.com" } }"
    
  2. Push, but do not start, your app:

    cf push -f ./manifest.yml --no-start -b BUILDPACK-NAME
    

    where BUILDPACK-NAME is the name you chose for your custom buildpack, or it is the URL of the most recent Java buildpack version, if you did not create a custom buildpack.

    The specification of the buildpack on the cf push command line takes precedence over specification within the manifest.

    For Pivotal Cloud Cache version 1.12 or 1.11, use the URL for the v4.35 buildpack if you did not create a custom buildpack. For the v4.35 buildpack, the cf push command becomes:

    $ cf push -f ./manifest.yml --no-start -b https://github.com/cloudfoundry/java-buildpack.git#v4.35
    
  3. Bind and start your app:

    cf bind-service APP-NAME SERVICE-INSTANCE-NAME
    
    cf start APP-NAME
    
  4. To verify that near caching is disabled for the app, use cf ssh to access the app and visually verify that enableLocalCache='false' appears within the context.xml file. Use this sequence of commands:

    cf ssh APP-NAME
    
    cat app/.java-buildpack/tomcat/conf/context.xml