spring-projects / spring-session

Spring Session
https://spring.io/projects/spring-session
Apache License 2.0
1.86k stars 1.12k forks source link

easier configuration of session timeout #110

Closed NoUsername closed 9 years ago

NoUsername commented 9 years ago

currently the session timeout can be set via the @EnableRedisHttpSession(maxInactiveIntervalInSeconds=3600) annotation

however this value will often be externalized (as it is already with spring boot applications in the server.session-timeout property.

it would be nice to have an easy way to configure this more dynamically. either via allowing a spring-expression in the annotation or by providing a simple setter on a bean that can be auto-injected and customized somewhere

rwinch commented 9 years ago

At the moment I don't really see this as being a common use case. I'm hesitant to introduce additional complexity without a popular usecase(s). Perhaps if you explain your use case I will better understand.

The way in which you would do this currently is by providing your own SessionRepository and ensuring to mark it as @Primary. For example:

@EnableRedisHttpSession
public class HttpSessionConfig {
    @Value("${server.session-timeout}")
    private int maxInactiveIntervalInSeconds;

    @Primary
    @Bean
    public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, ExpiringSession> sessionRedisTemplate) {
        RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(sessionRedisTemplate);
        sessionRepository.setDefaultMaxInactiveInterval(maxInactiveIntervalInSeconds);
        return sessionRepository;
    }
}
NoUsername commented 9 years ago

Ah, I didn't think of that solution. It seems I didn't fully understand how to take advantage of overriding Spring beans.

Just tried it and it works perfectly, thank you! (only @RedisHttpSessionConfiguration from your example should be @EnableRedisHttpSession)

I think the code snippet above would be a good addition to the documentation, as I think that it's a common use-case to change the default session-timeout.

My use-case is that the application can run in clustered mode and without clustered mode. Non-clustered mode is typically used in dev environments and on the dev-server. the staging server then already uses clustered mode (to test the proxy configuration and failover etc) and the production system also uses it obviously.

So the use-case for having "dynamic" configuration is that for non-clustered mode we use the normal spring-boot approach to configure tomcats session timeout via server.session-timeout and we want to use the same value for clustered mode without duplicating the value anywhere else.

Thanks again for the feedback and also for this great project :+1:

rwinch commented 9 years ago

Just tried it and it works perfectly, thank you! (only @RedisHttpSessionConfiguration from your example should be @EnableRedisHttpSession)

Thanks I updated the code.

I think the code snippet above would be a good addition to the documentation, as I think that it's a common use-case to change the default session-timeout.

You are right that this should be included in the documentation. I created #114 to address this

Thanks again for the feedback and also for this great project

Thank you for trying it out and providing feedback :)

tcesenthil commented 9 years ago

Hi I defined "server.session-timeout=15" in application.properties file and followed the above approach to my HttpSessionConfig file (as listed below). My Session was not automatically destroyed after 15 seconds.

I had placed a print statement during the SessionDestroyedEvent event. This statement got triggered when the timeout was hard-coded via the annotation or when programmatically set but, it never worked when i defined it via application.properties.

What could be the reason ? or am i missing something ?

@Configuration //@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 30) @EnableRedisHttpSession public class HttpSessionConfig {

@Value("${server.session-timeout}")
private int maxInactiveIntervalInSeconds;   
NoUsername commented 9 years ago

Did you also define the RedisOperationsSessionRepository bean and defined it as a @Primary bean (like in rwinch's first answer)?

Because this worked for me (tested) and is used in production - not 100% sure about the spring-session version we currently use though.

tcesenthil commented 9 years ago

Yes, here is the code

import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.session.ExpiringSession; import org.springframework.session.data.redis.RedisOperationsSessionRepository; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;

@Configuration //@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 30) @EnableRedisHttpSession public class HttpSessionConfig {

@Value("${server.session-timeout}")
private int maxInactiveIntervalInSeconds;   

@Primary
@Bean
public RedisOperationsSessionRepository sessionRepository(RedisTemplate<String, ExpiringSession> sessionRedisTemplate) {
    RedisOperationsSessionRepository sessionRepository = new RedisOperationsSessionRepository(sessionRedisTemplate);
    sessionRepository.setDefaultMaxInactiveInterval(maxInactiveIntervalInSeconds);
    return sessionRepository;
}   

@Bean
public JedisConnectionFactory connectionFactory() {
    return new JedisConnectionFactory();
}

@Bean
public RedisTemplate<String, Customer> name(
        RedisConnectionFactory connectionFactory) {
    RedisTemplate<String, Customer> redisTemplate = new RedisTemplate<String, Customer>();
    redisTemplate.setConnectionFactory(connectionFactory);
    return redisTemplate;
}

}

tcesenthil commented 9 years ago

If i uncomment the annotation based definition of maxInactiveIntervalInSeconds , auto expiry happens exactly after 30 seconds. It is only the value that comes from the application.properties that doesn't seems to work. The destroyed event statement is not getting printed at all, however long it takes.

tcesenthil commented 9 years ago

any pointers anyone ? the external configuration value is being picked up but session is not Auto-expiring after that many seconds.

smishra commented 7 years ago

Have you tried setting your server.session.timeout - if you are using SpringBoot that may be the one overriding your session timeouts.

imarchuang commented 6 years ago

@tcesenthil This might be too late for your question. When you say "not Auto-expiring" after the configured timeout, do you mean the object is not removed from Redis? As spring-session only cleans up the session objects in Redis 5 minutes after it's been expired.