Joget Clustering using Tomcat Session Replication

Configuring Tomcat's Persistent Manager allows for the exchange of active but inactive sessions for persistent storage and preserves all sessions during a regular Tomcat restart. Additionally, with the provided SQL scripts, you can set up a database to store session information using JDBC.

Setting up Joget Clustering using Session Replication in Tomcat is important for ensuring the availability and scalability of your Joget application. This configuration allows workload distribution among multiple servers, ensuring continuous session activity and persistence, even during restarts.

Configuration changes
Recent updates to Tomcat have deprecated the PersistentValve configuration. It is recommended to use a load balancer with sticky sessions for session replication. This guide covers only Tomcat configuration; for additional clustering configurations, such as setting up a shared directory, see the Server Clustering Guide.

Next, follow these steps to configure session persistence in Tomcat:

  1. Add the jvmRoute parameter to the <Engine> tag in the server.xml file:
    <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">
  2. In the catalina.properties file, ensure to add the following line:
    org.apache.catalina.session.StandardSession.ACTIVITY_CHECK=true
    This is necessary to ensure proper functionality of the persistent manager.

For this guide, a JDBC (Java Database Connectivity) Based Storage is used to store sessions in individual rows of a preconfigured table in a database accessed through a JDBC driver.

  1. Next, create a database named tomcat and table to store session data. Execute the following SQL queries for your specific database system:
    • MySQL/MariaDB
      CREATE DATABASE tomcat;
      GRANT ALL PRIVILEGES ON tomcat.* TO 'tomcat'@'%' IDENTIFIED BY 'tomcat';
      USE tomcat;
      CREATE TABLE tomcat_sessions (
        session_id VARCHAR(100) NOT NULL PRIMARY KEY,
        valid_session CHAR(1) NOT NULL,
        max_inactive INT NOT NULL,
        last_access BIGINT NOT NULL,
        app_name VARCHAR(255),
        session_data MEDIUMBLOB,
        KEY kapp_name (app_name)
      );
    • MSSQL
      CREATE DATABASE tomcat;
      CREATE LOGIN tomcat WITH PASSWORD = 'tomcat';
      CREATE USER tomcat FOR LOGIN tomcat;
      USE tomcat;
      CREATE TABLE tomcat_sessions (
        session_id VARCHAR(100) NOT NULL PRIMARY KEY,
        valid_session CHAR(1) NOT NULL,
        max_inactive INT NOT NULL,
        last_access BIGINT NOT NULL,
        app_name VARCHAR(255),
        session_data VARBINARY(MAX),
      );
      CREATE INDEX kapp_name ON tomcat_sessions (app_name);
      ALTER ROLE db_owner ADD MEMBER tomcat;
    • PostgreSQL
      CREATE DATABASE tomcat;
      CREATE USER tomcat WITH PASSWORD 'tomcat';
      GRANT ALL PRIVILEGES ON DATABASE tomcat TO tomcat;
      ALTER DATABASE tomcat OWNER TO tomcat;
      \c tomcat tomcat;
      CREATE TABLE tomcat_sessions (
        session_id CHARACTER VARYING(100) NOT NULL,
        valid_session CHARACTER(1) NOT NULL,
        max_inactive INTEGER NOT NULL,
        last_access BIGINT NOT NULL,
        app_name CHARACTER VARYING(255),
        session_data BYTEA,
        CONSTRAINT tomcat_sessions_pkey PRIMARY KEY (session_id)
      );
      CREATE INDEX app_name_index ON tomcat_sessions USING btree (app_name);
  1. Place the necessary JDBC driver JAR file (depending on the type of database you are using) in the *[TOMCAT_PATH]\lib* directory. For example:

    • For MySQL, use the MySQL JDBC driver.
    • For MSSQL, use the MSSQL JDBC driver.
    • For PostgreSQL, use the PostgreSQL JDBC driver.

  2. Add the specific configurations to the [TOMCAT_PATH]\conf\context.xml file, according to the database management system you are using. Make sure to replace [YourDBIPHere] and [YourDBPortHere] with your database's IP address and port, respectively. Here are the configuration snippets for each database type:

    • For MySQL/MariaDB:
      <Resources cachingAllowed="true" cacheMaxSize="100000" />
      <Manager className="org.apache.catalina.session.PersistentManager"
      maxIdleBackup="1"
      maxIdleSwap="1"
      minIdleSwap="0"
      processExpiresFrequency="1"
      saveOnRestart='true'>
        <Store className="org.apache.catalina.session.JDBCStore"
      connectionURL="jdbc:mysql://joget-db-server-ip/tomcat?user=tomcat&amp;password=tomcat"
      driverName="com.mysql.jdbc.Driver"
      sessionAppCol="app_name"
      sessionDataCol="session_data"
      sessionIdCol="session_id"
      sessionLastAccessedCol="last_access"
      sessionMaxInactiveCol="max_inactive"
      sessionTable="tomcat_sessions"
      sessionValidCol="valid_session"/> 
        </Manager>
    • For MSSQL:
      <Resources cachingAllowed="true" cacheMaxSize="100000" />
      <Manager className="org.apache.catalina.session.PersistentManager"
      maxIdleBackup="1"
      maxIdleSwap="1"
      minIdleSwap="0"
      processExpiresFrequency="1"
      saveOnRestart='true'>
        <Store className="org.apache.catalina.session.JDBCStore"
      connectionURL="jdbc:sqlserver://joget-db-server-ip:1433&amp;databaseName=tomcat&amp;user=tomcat&amp;password=tomcat&amp;encrypt=false&amp;trustServerCertificate=false"
      driverName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
      sessionAppCol="app_name"
      sessionDataCol="session_data"
      sessionIdCol="session_id"
      sessionLastAccessedCol="last_access"
      sessionMaxInactiveCol="max_inactive"
      sessionTable="tomcat_sessions"
      sessionValidCol="valid_session"/> 
        </Manager>
    • For MSSQL:
      <Resources cachingAllowed="true" cacheMaxSize="100000" />
      <Manager className="org.apache.catalina.session.PersistentManager"
      maxIdleBackup="1"
      maxIdleSwap="1"
      minIdleSwap="0"
      processExpiresFrequency="1"
      saveOnRestart='true'>
        <Store className="org.apache.catalina.session.JDBCStore"
      connectionURL="jdbc:postgresql://[YourDBIPHere]:[YourDBPortHere]/tomcat?user=tomcat&amp;password=tomcat"
      driverName="org.postgresql.Driver"
      sessionAppCol="app_name"
      sessionDataCol="session_data"
      sessionIdCol="session_id"
      sessionLastAccessedCol="last_access"
      sessionMaxInactiveCol="max_inactive"
      sessionTable="public.tomcat_sessions"
      sessionValidCol="valid_session"/> 
        </Manager>
      Note: For file-based session management methods, see the official Tomcat documentation.
Created by Julieth Last modified by Aadrian on Dec 13, 2024