Giter Club home page Giter Club logo

tomcat-redis-session-manager's Introduction

Redis Session Manager for Apache Tomcat

Overview

An session manager implementation that stores sessions in Redis for easy distribution of requests across a cluster of Tomcat servers. Sessions are implemented as as non-sticky--that is, each request is able to go to any server in the cluster (unlike the Apache provided Tomcat clustering setup.)

Sessions are stored into Redis immediately upon creation for use by other servers. Sessions are loaded as requested directly from Redis (but subsequent requests for the session during the same request context will return a ThreadLocal cache rather than hitting Redis multiple times.) In order to prevent collisions (and lost writes) as much as possible, session data is only updated in Redis if the session has been modified.

The manager relies on the native expiration capability of Redis to expire keys for automatic session expiration to avoid the overhead of constantly searching the entire list of sessions for expired sessions.

Data stored in the session must be Serializable.

Support this project!

This is an open-source project. Currently I'm not using this for anything personal or professional, so I'm not able to commit much time to the project, though I attempt to merge in reasonable pull requests. If you like to support further development of this project, you can donate via Pledgie:

Click here to lend your support to: Tomcat Redis Session Manager and make a donation at pledgie.com !

Commercial Support

If your business depends on Tomcat and persistent sessions and you need a specific feature this project doesn't yet support, a quick bug fix you don't have time to author, or commercial support when things go wrong, I can provide support on a contractual support through my consultancy, Orange Function, LLC. If you have any questions or would like to begin discussing a deal, please contact me via email at [email protected].

Tomcat Versions

This project supports both Tomcat 6 and Tomcat 7. Starting at project version 1.1, precompiled JAR downloads are available for either version of Tomcat while project versions before 1.1 are only available for Tomcat 6.

The official release branches in Git are as follows:

  • master: Continuing work for Tomcat 7 releases. Compatible with Java 7.
  • tomcat-6: Deprecated; may accept submitted patches, but no new work is being done on this branch. Compatible with Tomcat 6 and Java 6.

Finalized branches include:

  • tomcat-7: Has been merged into master. Compatible with Java 6 or 7.
  • java-7: Has been merged into master. All of the work from master for Tomcat 7 but taking advantage of new features in Java 7. Compatible with Java 7 only.

Tomcat 8

Tomcat 8 is not currently supported and has not been tested or developed for at all In fact, as noted in various bug reports, the project currently fails to compile when linked with Tomcat 8.

I currently don't have the time to add Tomcat 8 support in my spare time. However if you're interested in Tomcat 8 support for your particular use case and/or business, as the README notes, I'm available as a consultancy on a contractual basis. If you'd like to pursue getting this feature added at a contract rate (and gain some commercial support as well), feel free to contact me at [email protected].

Architecture

  • RedisSessionManager: provides the session creation, saving, and loading functionality.
  • RedisSessionHandlerValve: ensures that sessions are saved after a request is finished processing.

Note: this architecture differs from the Apache PersistentManager implementation which implements persistent sticky sessions. Because that implementation expects all requests from a specific session to be routed to the same server, the timing persistence of sessions is non-deterministic since it is primarily for failover capabilities.

Usage

Add the following into your Tomcat context.xml (or the context block of the server.xml if applicable.)

<Valve className="com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve" />
<Manager className="com.orangefunction.tomcat.redissessions.RedisSessionManager"
         host="localhost" <!-- optional: defaults to "localhost" -->
         port="6379" <!-- optional: defaults to "6379" -->
         database="0" <!-- optional: defaults to "0" -->
         maxInactiveInterval="60" <!-- optional: defaults to "60" (in seconds) -->
         sessionPersistPolicies="PERSIST_POLICY_1,PERSIST_POLICY_2,.." <!-- optional -->
         sentinelMaster="SentinelMasterName" <!-- optional -->
         sentinels="sentinel-host-1:port,sentinel-host-2:port,.." <!-- optional --> />

The Valve must be declared before the Manager.

Copy the following files into the TOMCAT_BASE/lib directory:

  • tomcat-redis-session-manager-VERSION.jar
  • jedis-2.5.2.jar
  • commons-pool2-2.2.jar

Reboot the server, and sessions should now be stored in Redis.

Connection Pool Configuration

All of the configuration options from both org.apache.commons.pool2.impl.GenericObjectPoolConfig and org.apache.commons.pool2.impl.BaseObjectPoolConfig are also configurable for the Redis connection pool used by the session manager. To configure any of these attributes (e.g., maxIdle and testOnBorrow) just use the config attribute name prefixed with connectionPool (e.g., connectionPoolMaxIdle and connectionPoolTestOnBorrow) and set the desired value in the <Manager> declaration in your Tomcat context.xml.

Session Change Tracking

As noted in the "Overview" section above, in order to prevent colliding writes, the Redis Session Manager only serializes the session object into Redis if the session object has changed (it always updates the expiration separately however.) This dirty tracking marks the session as needing serialization according to the following rules:

  • Calling session.removeAttribute(key) always marks the session as dirty (needing serialization.)
  • Calling session.setAttribute(key, newAttributeValue) marks the session as dirty if any of the following are true:
    • previousAttributeValue == null && newAttributeValue != null
    • previousAttributeValue != null && newAttributeValue == null
    • !newAttributeValue.getClass().isInstance(previousAttributeValue)
    • !newAttributeValue.equals(previousAttributeValue)

This feature can have the unintended consequence of hiding writes if you implicitly change a key in the session or if the object's equality does not change even though the key is updated. For example, assuming the session already contains the key "myArray" with an Array instance as its corresponding value, and has been previously serialized, the following code would not cause the session to be serialized again:

List myArray = session.getAttribute("myArray");
myArray.add(additionalArrayValue);

If your code makes these kind of changes, then the RedisSession provides a mechanism by which you can mark the session as dirty in order to guarantee serialization at the end of the request. For example:

List myArray = session.getAttribute("myArray");
myArray.add(additionalArrayValue);
session.setAttribute("__changed__");

In order to not cause issues with an application that may already use the key "__changed__", this feature is disabled by default. To enable this feature, simple call the following code in your application's initialization:

RedisSession.setManualDirtyTrackingSupportEnabled(true);

This feature also allows the attribute key used to mark the session as dirty to be changed. For example, if you executed the following:

RedisSession.setManualDirtyTrackingAttributeKey("customDirtyFlag");

Then the example above would look like this:

List myArray = session.getAttribute("myArray");
myArray.add(additionalArrayValue);
session.setAttribute("customDirtyFlag");

Persistence Policies

With an persistent session storage there is going to be the distinct possibility of race conditions when requests for the same session overlap/occur concurrently. Additionally, because the session manager works by serializing the entire session object into Redis, concurrent updating of the session will exhibit last-write-wins behavior for the entire session (not just specific session attributes).

Since each situation is different, the manager gives you several options which control the details of when/how sessions are persisted. Each of the following options may be selected by setting the sessionPersistPolicies="PERSIST_POLICY_1,PERSIST_POLICY_2,.." attributes in your manager declaration in Tomcat's context.xml. Unless noted otherwise, the various options are all combinable.

  • SAVE_ON_CHANGE: every time session.setAttribute() or session.removeAttribute() is called the session will be saved. Note: This feature cannot detect changes made to objects already stored in a specific session attribute. Tradeoffs: This option will degrade performance slightly as any change to the session will save the session synchronously to Redis.
  • ALWAYS_SAVE_AFTER_REQUEST: force saving after every request, regardless of whether or not the manager has detected changes to the session. This option is particularly useful if you make changes to objects already stored in a specific session attribute. Tradeoff: This option make actually increase the liklihood of race conditions if not all of your requests change the session.

Testing/Example App

For full integration testing as well as a demonstration of how to use the session manager, this project contains an example app and a virtual server setup via Vagrant and Chef.

To get the example server up and running, you'll need to do the following:

  1. Download and install Virtual Box (4.3.12 at the time of this writing) from https://www.virtualbox.org/wiki/Downloads
  2. Download and install the latest version (1.6.3 at the time of this writing) of Vagrant from http://www.vagrantup.com/downloads.html
  3. Install Ruby, if necessary.
  4. Install Berkshelf with gem install berkshelf
  5. Install the Vagrant Berkshelf plugin with vagrant plugin install vagrant-berkshelf --plugin-version '>= 2.0.1'
  6. Install the Vagrant Cachier plugin for speed with vagrant plugin install vagrant-cachier
  7. Install the Vagrant Omnibus plugin with vagrant plugin install vagrant-omnibus
  8. Install the required Ruby gems with PROJECT_ROOT/bundle install
  9. Boot the virtual machine with PROJECT_ROOT/vagrant up
  10. Run the tests with PROJECT_ROOT/rspec

Acknowledgements

The architecture of this project was based on the Mongo-Tomcat-Sessions project found at https://github.com/dawsonsystems/Mongo-Tomcat-Sessions

tomcat-redis-session-manager's People

Contributors

dependabot[bot] avatar farvilain avatar harker2015 avatar heikkipora avatar jcoleman avatar jheilgeist avatar mehiel avatar michaelcameron avatar peh avatar ssrini avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tomcat-redis-session-manager's Issues

NullPointException

at com.radiadesign.catalina.session.RedisSession.setAttribute(RedisSession.java:56)

Any idea why I would be getting a NPE here? Below is the object I'm trying to set in the session:

code causing error: getRequest().getSession().setAttribute("curSubNav", menuItem);

public class MenuItem implements Serializable {

private static final long serialVersionUID = -2178276806641481428L;

private Integer id;
private Integer parentMenuId;
private String name;
private String title;
private String link;

public MenuItem() {}

public MenuItem(String name, String title) {
    this.name = name;
    this.title = title;
}

public Integer getId() {
    return id;
}
public void setId(Integer id) {
    this.id = id;
}
public Integer getParentMenuId() {
    return parentMenuId;
}
public void setParentMenuId(Integer parentMenuId) {
    this.parentMenuId = parentMenuId;
}
public String getName() {
    return name;
}
public void setName(String name) {
    this.name = name;
}
public String getTitle() {
    return title;
}
public void setTitle(String title) {
    this.title = title;
}
public String getLink() {
    return link;
}
public void setLink(String link) {
    this.link = link;
}

}

Java 8 with tomcat 7 Support

Hi,
This library looks pretty solid for Java 7 with tomcat 7. I'm assuming it would also be compatible for "Java 8 with tomcat 7"? Is there anything else I should do or it should just work as it?
Any feedback is really really appreciated.

Thanks

RedisSessionManager.createSession returns session even if ID was not unique

In do-while block there is

while (jedis.setnx(sessionId.getBytes(), NULL_SESSION) == 1L); // 1 = key set; 0 = key already existed

Doesn't this cause running the loop two times when key does not exist (first invocation returns 1L) and if there is duplicate key it will just continue and return conflicting session?

RedisSession.java

We were getting a Null pointer exception in SetAttribute(). THe current code is:

public void setAttribute(String key, Object value) {
Object oldValue = getAttribute(key);
if ( value == null && oldValue != null
|| oldValue != null && value == null
|| !value.getClass().isInstance(oldValue)
|| !value.equals(oldValue) ) {
changedAttributes.put(key, value);
}

Shouldn't this actually be
if ( value == null && oldValue != null
|| oldValue == null && value != null

Currently both conditions are the same. Please advise.

How to set a session to timeout in 2 minutes as I set maxInactiveInterval(in ROOT.xml)?

Hi, I'm testing with sharing sessions using tomcat-redis-session-manager jar.
Sessions are stored in Redis as I expected but session timeout is not working.

I understand that if I set maxInactiveInterval=120(ROOT.xml) then session will be expired in 2 minutes.
But whether or not I configures session maxInactiveInterval, session expired in 5 minutes.
It seems maxInactiveInterval doesn't work. Did I misunderstand something?

I'm wondering if I programatically set the time limit of inactivity by

request.getSession().setMaxInactiveInterval(7* 60); //7 minutes

I think session timeout minutes this configuration has high priority but session expired in 5 minutes(web.xml configurataion).

Currently, we have our session timeout set in the Catalina/ROOT.xml file, like this

<Context path="/">
  <Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
  <Manager className="com.radiadesign.catalina.session.RedisSessionManager"
    host="x.x.x.x."
    port="6380"
    password="xxxx"
    database="0"
    maxInactiveInterval="120" />
</Context>

and myapplication/web.xml file

<session-config>
    <session-timeout>5</session-timeout>
  </session-config>
...



* Using

Tomcat 7 version
Java 1.7.0_65 version
tomcat-redis-session-manager-1.2-tomcat-7-java-7.jar
jedis-2.1.0.jar
commons-pool-1.6.jar

I added these jars in Tomcat/lib and reboot the server. 

Thank you in advance.

TTL of sessions not updated despite activity of session

Hi,
I'm currently evaluating to use your project. It works so far, but it seems to not behave as expected. In my application the session usually changes only once after the user authenticates. The user than continues to perform authenticated requests. But the session is gone after the amount of seconds I've entered for maxInactiveInterval, although the user was active all the time (performing requests). It seems for me, that the maxInactiveInterval is set as the TTL for the redis entry, but it is not updated when the user performs requests.
Can you confirm this? If yes, is it a bug or is there a reason for that behaviour?

Thanks in advance.

Cheers
Nico

SEVERE: Unable to deserialize into session

java.lang.ClassNotFoundException: com.jiuying.user.entity.logic.JydUserLogic
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:266)
at org.apache.catalina.util.CustomObjectInputStream.resolveClass(CustomObjectInputStream.java:74)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1593)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1514)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1750)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1347)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:369)
at org.apache.catalina.session.StandardSession.readObject(StandardSession.java:1619)
at org.apache.catalina.session.StandardSession.readObjectData(StandardSession.java:1084)
at com.orangefunction.tomcat.redissessions.RedisSession.readObjectData(RedisSession.java:119)
at com.orangefunction.tomcat.redissessions.JavaSerializer.deserializeInto(JavaSerializer.java:76)
at com.orangefunction.tomcat.redissessions.RedisSessionManager.sessionFromSerializedData(RedisSessionManager.java:530)
at com.orangefunction.tomcat.redissessions.RedisSessionManager.findSession(RedisSessionManager.java:432)
at org.apache.catalina.connector.Request.doGetSession(Request.java:2913)
at org.apache.catalina.connector.Request.getSessionInternal(Request.java:2531)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:426)
at com.orangefunction.tomcat.redissessions.RedisSessionHandlerValve.invoke(RedisSessionHandlerValve.java:22)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1736)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1695)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)

RedisSession throw NullPointException

in the method setAttribute

if ( (value != null || oldValue != null)
&& ( value == null && oldValue != null
|| oldValue == null && value != null
|| !value.getClass().isInstance(oldValue)
|| !value.equals(oldValue) ) ) {

not handled

if (value == null && oldValue == null)

Unable to use tomcat redis session manager latest version on tomcat 7

Hi James Coleman,

I have an application where I'm trying to use this session manager but upon starting tomcat, I get the following error:

java.lang.VerifyError: Bad type on operand stack in method com.radiadesign.catalina.session.RedisSessionManager.initializeDatabaseConnection

Here are the libraries I've included under tomcat_home/lib:

  1. commons-pool-1.6.jar
  2. commons-pool2-2.2.jar
  3. tomcat-redis-session-manager-1.2-tomcat-7.jar
  4. jedis-2.5.2.jar

Am I missing any configuration?

Race condition encountered: attempted to load session[SESSION_ID] which has been created but not yet serialized.

We are getting this error in Production while using Tomcat 6 version of the redis session manager. Since saveOnChange feature doesn't exist in this branch, we cannot use it (unfortunate). We would like to know what impact this exception has to the users.

In New Relic we see transactions with these errors have a 200 HTTP response code. Does this mean that the user did not receive errors(maybe because of a retry somewhere)? Also there are 100's of such errors everyday in our logs but haven't heard any issues reported from our users or testers.

Please advice.

Don't get session in the redis

String id = request.getSession().getId();
System.err.println(id);
RedisSessionManager manager=new RedisSessionManager();
RedisSession loadSessionFromRedis = manager.loadSessionFromRedis(id);

java.lang.NullPointerException
at com.radiadesign.catalina.session.RedisSessionManager.acquireConnection(RedisSessionManager.java:108)
at com.radiadesign.catalina.session.RedisSessionManager.loadSessionFromRedis(RedisSessionManager.java:399)
I think connectionPool is null
who can help me ???? thinks

How to build a jar compatible with tomcat 7 and java 1.6?

I am not familiar with gradle, so please correct me if i am not using it appropriately. I checked out the master branch of the repo, changed the sourceCompatibility and targetCompatibility to 1.6 in build.gradle and run 'gradle build'. There are 4 places in code which are not compatible with java 1.6. Then I tried in tomcat-7 branch and import 'tomcat-redis-session-manager-1.1.jar' into my project. It is complaining 'Unsupported major.minor version 51.0'. Still the java version.

Would you like to tell me how to build a jar compatible with tomcat 7 and java 1.6? Thanks.

updating existing object in session is not reflecting in redis server

We are using redis with tomcat I added configuration for redis in tomcat context.xml like this

When we add some data in session it is adding to redis. When i add new objects it is reflecting but when i try to modify existing object attributes it is not reflecting in redis.

Session change tracking is there in this article but can u suggest how to do it in context.xml.
Is there any tag or attribute to do this session change tracking.

What is the solution for this can u suggest.

redis.clients.jedis.exceptions.JedisDataException: ERR unknown command 'SENTINEL'

Tomcat 7.0.56 JDK1.7.0_17

context.xml


org.apache.catalina.LifecycleException: Failed to start component [com.orangefunction.tomcat.redissessions.RedisSessionManager[]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5192)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:724)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:700)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:714)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1071)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1722)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Caused by: org.apache.catalina.LifecycleException: Error connecting to Redis
at com.orangefunction.tomcat.redissessions.RedisSessionManager.initializeDatabaseConnection(RedisSessionManager.java:663)
at com.orangefunction.tomcat.redissessions.RedisSessionManager.startInternal(RedisSessionManager.java:298)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 13 more
Caused by: redis.clients.jedis.exceptions.JedisDataException: ERR unknown command 'SENTINEL'
at redis.clients.jedis.Protocol.processError(Protocol.java:113)
at redis.clients.jedis.Protocol.process(Protocol.java:131)
at redis.clients.jedis.Protocol.read(Protocol.java:200)
at redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:285)
at redis.clients.jedis.Connection.getRawObjectMultiBulkReply(Connection.java:230)
at redis.clients.jedis.Connection.getObjectMultiBulkReply(Connection.java:236)
at redis.clients.jedis.Jedis.sentinelGetMasterAddrByName(Jedis.java:3007)
at redis.clients.jedis.JedisSentinelPool.initSentinels(JedisSentinelPool.java:122)
at redis.clients.jedis.JedisSentinelPool.(JedisSentinelPool.java:73)
at redis.clients.jedis.JedisSentinelPool.(JedisSentinelPool.java:49)
at com.orangefunction.tomcat.redissessions.RedisSessionManager.initializeDatabaseConnection(RedisSessionManager.java:654)
... 15 more

Java 6 support

I am trying to setup redis tomcat session provider in the following environment - Tomcat 1.7 and JDK 1.6. Based on the documentation I have built war file from tomcat-7 branch. Basic setup is functional, but some areas of the application do not work as expected because of the dirty tracking.

I tried to set Persistence Policies with both options "SAVE_ON_CHANGE" and "ALWAYS_SAVE_AFTER_REQUEST", but looks like the Persistence Policies are not implemented in the tomcat-7 branch. On Tomcat startup I am getting this "WARNING: [SetPropertiesRule]{Context/Manager} Setting property 'sessionPersistPolicies' to 'SAVE_ON_CHANGE,ALWAYS_SAVE_AFTER_REQUEST' did not find a matching property."

I tried to set the session change tracking using RedisSession.setManualDirtyTrackingSupportEnabled(true), but looks like there is no way to set this because the method is non-static in tomcat-7 branch and there is no way to cast the session object to a RedisSession. In the master branch I see the method is static.

Am I missing something here or is the support for Java 6 deprecated?

Servlet 3+ async requests support

Does tomcat-redis-session-manager support Servlet 3+ async requests? Is that enough to change RedisSessionHandlerValve constuctors to allow putting requests in async mode?
I.e.
public RedisSessionHandlerValve() {
super(true); // instead of super();
}

which will call

public ValveBase() {
    this(false);
}

public ValveBase(boolean asyncSupported) {
    this.asyncSupported = asyncSupported;
}

Compile failed with Tomcat 8

In RedisSessionManager.java, Line 716:

 if (getContainer() != null) {
  loader = getContainer().getLoader();
}

The getLoader() method is removed in Tomcat 8.

Having problem with login-config

branch tomcat-6
tomcat tomcat-6.0.39
servlet 2.4

I have tested web application with following login-config.

    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/login_form.jsp</form-login-page>
            <form-error-page>/login_error.jsp</form-error-page>
        </form-login-config>
    </login-config>
    <!-- with security-role, security-constraint -->

When client request arrived, findSession is called more then once
and currentSessionId is always .seted (first time, second time. doesn't matter)
but currentSession has nowhere .set

2nd call findSession

  @Override
  public Session findSession(String id) throws IOException {
    RedisSession session;

    if (id == null) {
      session = null;
      currentSessionIsPersisted.set(false);
    } else if (id.equals(currentSessionId.get())) {
      session = currentSession.get();
    } else {
      session = loadSessionFromRedis(id);

      if (session != null) {
        currentSessionIsPersisted.set(true);
      }
    }

    currentSession.set(session);
    currentSessionId.set(id);

    return session;
  }

The problem is else if.
currentSessionId equals id. but currentSession.get() is null.

ClassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool$Config

on tomcat start a have such exception.
I use tomcat 7.0.54,
tomcat-redis-session-manager-1.2-tomcat-7, jedis-2.4.2, commons-pool2-2.2 are in tomcat/lib directory.
config is default:

<Valve className="com.radiadesign.catalina.session.RedisSessionHandlerValve" />
<Manager className="com.radiadesign.catalina.session.RedisSessionManager"
             host="localhost" port="6379" database="0" maxInactiveInterval="60"  />

when i put commons-pool-1.6 in tomcat lib a have issue

 Type 'redis/clients/jedis/JedisPoolConfig'  is not assignable to 'org/apache/commons/pool/impl/GenericObjectPool$Config'

Caused by: java.lang.NoSuchFieldError: container

org.apache.catalina.LifecycleException: Failed to start component [com.orangefunction.tomcat.redissessions.RedisSessionManager[]]
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:154)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5192)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:724)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:700)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:714)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1071)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1722)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
Caused by: java.lang.NoSuchFieldError: container
at com.orangefunction.tomcat.redissessions.RedisSessionManager.initializeSerializer(RedisSessionManager.java:677)
at com.orangefunction.tomcat.redissessions.RedisSessionManager.startInternal(RedisSessionManager.java:294)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
... 13 more

jdk1.7.0-17 /tomcat 7.055

NullPointerException line RedisSessionManager:268

I get a null pointer exception tehre, it seems like this happens when there is no Sesison ID Requested at all, I also see that it could be that for sessionId.getBytes() sessionId can still be null at this point...

Jeddis connection is etablished nad nothing in the lifecycle about a failure connection

createSession() permit duplicated sesssionId

In RedisSessionManager#createSession(), jedis.setnx() returns 0L even if the sessionId already exists on Redis. In this case, a sessionId will be created for different RedisSession object.
So while-loop should repeat procedure if jedis.setnx() == 0L .

And in the while-loop, sessionId must re-generate if and only if argument is null.
When sessionId specified in argument, createSession() should return null on failure. (see Manager#createSession)

RedisSessionHandlerValve -> NullPointerException

All I get hen i do a request ist this null pointer exception, When i Track down the source it seems like there is no RedisSessionManager and I simply don't understand why I should have missed something in the configuration, I use it via the server.xml

java.lang.NullPointerException
at com.radiadesign.catalina.session.RedisSessionHandlerValve.invoke(RedisSessionHandlerValve.java:30)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:744)

Update dependency

But I'm not sure if this is available.. because already many servers use 'jedis 2.0.0' for this.

NPE in RedisSession.setAttribute("key", newAttributeValue) when newAttributeValue == null and previousAttributeValue != null

When running a large app that was working fine with normal Tomcat sessions, the following exception occurred:

java.lang.NullPointerException
    at com.radiadesign.catalina.session.RedisSession.setAttribute(RedisSession.java:56)
    at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:156)
    at com.example.redacted.app.controller.FooController.bar(FooController.java:321)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
...

The code in question in the application was calling session.setAttribute("myKey", null) in order to remove a key from the session. The key's previous attribute value had been set to a non-null value.

The [interface for HttpSession explicitly supports](http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpSession.html#setAttribute%28java.lang.String, java.lang.Object%29) calling setAttribute this way. The Java docs say "If the value passed in is null, this has the same effect as calling removeAttribute()."

There is a subtle logic problem in the session change tracking that falls through to a line where value.getClass().isInstance(oldValue) is invoked, but value is null.

I'm working on a fix and will attach a pull request as soon as I have a test case that verifies that it is working as expected. Work in progress on this is in this branch: https://github.com/ModusCreateOrg/tomcat-redis-session-manager/tree/nullfix

wrong condition checking in setAttribute()

"!value.equals(oldValue)"
this always be fasle,because value and oldValue alway be the same Object!
i suggest ,don't validate, set dirty = true directly.Because someone invoke setAttribute method always want to set something new into the session.

The method getLoader() is undefined for the type Container

if (getContainer() != null) {
loader = getContainer().getLoader();
}

The method getLoader() is undefined for the type Container

Env: jdk1.7.0_67 & Tomcat 8.0.12

Code From:

private void initializeSerializer() throws ClassNotFoundException, IllegalAccessException, InstantiationException {
log.info("Attempting to use serializer :" + serializationStrategyClass);
serializer = (Serializer) Class.forName(serializationStrategyClass).newInstance();

Loader loader = null;

if (getContainer() != null) {
  loader = getContainer().getLoader();
}

ClassLoader classLoader = null;

if (loader != null) {
     classLoader = loader.getClassLoader();
}
serializer.setClassLoader(classLoader);

}

NOAUTH Authentication required.

After i configured redis with password protected i get below error
Exception Occured
Exception Message --> NOAUTH Authentication required.
Exception Cause --> redis.clients.jedis.exceptions.JedisDataException: NOAUTH Authentication required.
File Name : SecurityInterceptor.java
Class Name : org.tcs.com.security.filter.SecurityInterceptor
Method Name : doFilter
Line No : 68

Refer below
error

Note: I dono where to enter password for redid

Redis HA Support

Hi, have you ever thought of supporting redis high availability features such a being able to change the redis host on runtime if the redis server crashes?
Redis addresses using Sentinel (http://redis.io/topics/sentinel), the RedisSessionManager should be able figure out if the redis server is down and automatically change the host to the promoted server (maybe by scanning a file container the current master address...)

why i setAttibute(key,null) ,i find this error?

hi,jcoleman:
why i setAttibute(key,null) ,i find this error:
java.lang.NullPointerException
at com.radiadesign.catalina.session.RedisSession.setAttribute(RedisSession.java:58)
at org.apache.catalina.session.StandardSessionFacade.setAttribute(StandardSessionFacade.java:154)
at org.apache.struts2.dispatcher.SessionMap.put(SessionMap.java:183)

Version Error

I am trying to implement your project and am getting this error when I startup tomcat:

java.lang.UnsupportedClassVersionError: com/radiadesign/catalina/session/RedisSessionHandlerValve : Unsupported major.minor version 51.0

Using
Tomcat 6
jedis-2.1.0.jar
tomcat-redis-session-manager-1.2-tomcat-6.jar

[root@ip-10-28-29-162 logs]# java -version
java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.3) (amazon-52.1.11.3.45.amzn1-x86_64)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)

exception about tomcat-redis-session-manager

@jcoleman

Dear, jcoleman

Where can i get the files that you mentioned :

tomcat-redis-session-manager-VERSION.jar
jedis-2.5.2.jar
commons-pool2-2.2.jar

i am using tomcat-redis-session-manager-1.2-tomcat-7-java-7.jar+++jedis-2.6.0.jar+++commons-pool2-2.0.jar

But it throw the excetion : java.lang.ClassNotFoundException: org.apache.commons.pool.impl.GenericObjectPool$Config when i start tomcat-7

Could u please do me a favour?

Thanks a lot

about race condition issue

I dont think "this should be incredibly unlikely". My app throws that error because using iframe in homepage. so maybe adding a configuration parameter is a good idea in order to reduce code dependency.

Which version is the latest version?

Dear jcoleman!

I am trying to get latest version of this session manager.
But i found the source distributed in 2012 years at release tab.
is this latest version?

if i download the source by button on the right side named 'Download zip',
it's different source with the version i downloaded in release tab.

which one is latest version?

please reply me.

Losing session values after jsp redirect (forward)

Hi,

I have installed redis, and I did the tomcat's integration with redis.
Everything works fine using session (set and get) on the same page (jsp), however if I redirect to another jsp, doesn't matter the way (javascript, jsp forward, etc), I lost the session data in the destination page. In summary, it seems the redirect doesn't work well, because it losts the session data.

This is tomcat setup in server.xml file:

Moreover we are using, the following jars:

tomcat-redis-session-manager-1.2-tomcat-7.jar
jedis-2.0.0.jar

Some code:

if (session.getAttribute("slogin") != null&&session.getAttribute("spassword") != null){
sLogin = (String)session.getAttribute("slogin");
sPassword= (String)session.getAttribute("spassword");
}

IDuser=oUsers.verifyUser();/log on/
if (IDuser>0) {
/* user ok /
session.setAttribute("slogin",sLogin.toLowerCase()); session.setAttribute("spassword",sPassword);
}
sTestValue=(String)session.getAttribute("slogin");
System.out.println("
* user in session("+sTestValue+") OK ");
mStatus=index;

<% if(mStatus.equalsIgnoreCase("index")){ %>
<script language="JavaScript" type="text/javascript">
backIndexPage(); <% // Return index.jsp %>
</script>
<%}%>

Thank you very much for your help,

Redis cluster support

Would it be possible to add support for redis cluster?
Redis 3.0 is stable now and Redis Cluster is introduced in this version.

java.lang.ClassCastException: com.orangefunction.tomcat.redissessions.SessionSerializationMetadata

hi

on latest master when trying to deserialize a session

java.lang.ClassCastException: com.orangefunction.tomcat.redissessions.SessionSerializationMetadata cannot be cast to com.orangefunction.tomcat.redissessions.SessionSerializationMetadata
    com.orangefunction.tomcat.redissessions.JavaSerializer.deserializeInto(JavaSerializer.java:76)
    com.orangefunction.tomcat.redissessions.RedisSessionManager.sessionFromSerializedData(RedisSessionManager.java:532)
    com.orangefunction.tomcat.redissessions.RedisSessionManager.findSession(RedisSessionManager.java:434)
    org.apache.catalina.connector.Request.doGetSession(Request.java:2865)
    org.apache.catalina.connector.Request.getSession(Request.java:2316)
    org.apache.catalina.connector.RequestFacade.getSession(RequestFacade.java:898)
    org.springframework.web.context.request.ServletRequestAttributes.updateAccessedSessionAttributes(ServletRequestAttributes.java:223)
    org.springframework.web.context.request.AbstractRequestAttributes.requestCompleted(AbstractRequestAttributes.java:48)
    org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest.requestCompleted(GrailsWebRequest.java:131)
    org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:72)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.codehaus.groovy.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:67)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:344)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:261)

Problem of Tomcat 7 compatibility

Hello, jcoleman.

I used tomcat-redis-session-manager with tomcat 7, but it doesn't work.
This exception would be thrown:

2012-1-13 10:14:50 org.apache.catalina.startup.HostConfig deployWAR
INFO: Deploying web application archive ROOT.war
2012-1-13 10:14:50 org.apache.tomcat.util.digester.Digester startElement
FATAL: Begin event threw error
java.lang.VerifyError: class com.radiadesign.catalina.session.RedisSessionManager overrides final method start.()V
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
        at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
        at org.apache.tomcat.util.digester.ObjectCreateRule.begin(ObjectCreateRule.java:144)
        at org.apache.tomcat.util.digester.Digester.startElement(Digester.java:1282)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:501)
        at com.sun.org.apache.xerces.internal.parsers.AbstractXMLDocumentParser.emptyElement(AbstractXMLDocumentParser.java:179)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanStartElement(XMLDocumentFragmentScannerImpl.java:1343)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2755)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
        at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
        at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
        at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
        at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1205)
        at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:522)
        at org.apache.tomcat.util.digester.Digester.parse(Digester.java:1543)
        at org.apache.catalina.startup.ContextConfig.processContextConfig(ContextConfig.java:636)
        at org.apache.catalina.startup.ContextConfig.contextConfig(ContextConfig.java:573)
        at org.apache.catalina.startup.ContextConfig.init(ContextConfig.java:841)
        at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:334)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:89)
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:379)
        at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:107)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:136)
        at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:812)
        at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:787)
        at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:607)
        at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:932)
        at org.apache.catalina.startup.HostConfig.deployWARs(HostConfig.java:723)
        at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:470)
        at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1322)
        at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:311)
        at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
        at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:89)
        at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:379)
        at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:324)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1041)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:774)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:1033)
        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:291)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:443)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:727)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:145)
        at org.apache.catalina.startup.Catalina.start(Catalina.java:620)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:303)
        at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:431)

Will tomcat 7 be supported in the future? Thanks.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.