diff --git a/docs/src/docs/asciidoc/index.adoc b/docs/src/docs/asciidoc/index.adoc index 70c1fcfd..bec6e6a7 100644 --- a/docs/src/docs/asciidoc/index.adoc +++ b/docs/src/docs/asciidoc/index.adoc @@ -321,6 +321,22 @@ It is the responsibility of the developer to ensure the attribute is populated s Some `SessionRepository` implementations may choose to implement `FindByUsernameSessionRepository` also. For example, Spring's Redis support implements `FindByUsernameSessionRepository`. +[[api-enablespringhttpsession]] +=== EnableSpringHttpSession + +The `@EnableSpringHttpSession` annotation can be added to an `@Configuration` class to expose the `SessionRepositoryFilter` as a bean named "springSessionRepositoryFilter". +In order to leverage the annotation, a single `SessionRepository` bean must be provided. +For example: + +[source,java,indent=0] +---- +include::{docs-test-dir}docs/SpringHttpSessionConfig.java[tags=class] +---- + +It is important to note that no infrastructure for session expirations is configured for you out of the box. +This is because things like session expiration are highly implementation dependent. +This means if you require cleaning up expired sessions, you are responsible for cleaning up the expired sessions. + [[api-redisoperationssessionrepository]] === RedisOperationsSessionRepository diff --git a/docs/src/test/java/docs/IndexDocTests.java b/docs/src/test/java/docs/IndexDocTests.java index fdf46914..c3db7df3 100644 --- a/docs/src/test/java/docs/IndexDocTests.java +++ b/docs/src/test/java/docs/IndexDocTests.java @@ -15,13 +15,20 @@ */ package docs; -import org.junit.Test; -import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; -import org.springframework.session.*; -import org.springframework.session.data.redis.RedisOperationsSessionRepository; - import static org.fest.assertions.Assertions.assertThat; +import org.junit.Test; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; +import org.springframework.mock.web.MockServletContext; +import org.springframework.session.ExpiringSession; +import org.springframework.session.MapSessionRepository; +import org.springframework.session.Session; +import org.springframework.session.SessionRepository; +import org.springframework.session.data.redis.RedisOperationsSessionRepository; +import org.springframework.session.web.http.SessionRepositoryFilter; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; + /** * @author Rob Winch */ @@ -104,6 +111,20 @@ public class IndexDocTests { // end::new-mapsessionrepository[] } + @Test + public void runSpringHttpSessionConfig() { + AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext(); + context.register(SpringHttpSessionConfig.class); + context.setServletContext(new MockServletContext()); + context.refresh(); + + try { + context.getBean(SessionRepositoryFilter.class); + } finally { + context.close(); + } + } + private static class User { private User(String username) {} } diff --git a/docs/src/test/java/docs/SpringHttpSessionConfig.java b/docs/src/test/java/docs/SpringHttpSessionConfig.java new file mode 100644 index 00000000..b7456e90 --- /dev/null +++ b/docs/src/test/java/docs/SpringHttpSessionConfig.java @@ -0,0 +1,32 @@ +/* + * Copyright 2002-2015 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. + */ +package docs; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.session.MapSessionRepository; +import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession; + +// tag::class[] +@EnableSpringHttpSession +@Configuration +public class SpringHttpSessionConfig { + @Bean + public MapSessionRepository sessionRepository() { + return new MapSessionRepository(); + } +} +// end::class[] \ No newline at end of file diff --git a/spring-session/src/main/java/org/springframework/session/config/annotation/web/http/EnableSpringHttpSession.java b/spring-session/src/main/java/org/springframework/session/config/annotation/web/http/EnableSpringHttpSession.java new file mode 100644 index 00000000..8ffdfc7d --- /dev/null +++ b/spring-session/src/main/java/org/springframework/session/config/annotation/web/http/EnableSpringHttpSession.java @@ -0,0 +1,82 @@ +/* + * Copyright 2002-2015 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. + */ +package org.springframework.session.config.annotation.web.http; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.session.SessionRepository; +import org.springframework.session.events.SessionCreatedEvent; +import org.springframework.session.events.SessionDestroyedEvent; + +/** + * Add this annotation to an {@code @Configuration} class to expose the + * SessionRepositoryFilter as a bean named "springSessionRepositoryFilter" and + * backed by a user provided implementation of {@link SessionRepository}. In + * order to leverage the annotation, a single {@link SessionRepository} bean + * must be provided. For example: + * + *
+ * 
+ * {@literal @Configuration}
+ * {@literal @EnableSpringHttpSession}
+ * public class SpringHttpSessionConfig {
+ *
+ *     {@literal @Bean}
+ *     public MapSessionRepository sessionRepository() {
+ *         return new MapSessionRepository();
+ *     }
+ *
+ * }
+ * 
+ * 
+ * + *

+ * It is important to note that no infrastructure for session expirations is + * configured for you out of the box. This is because things like session + * expiration are highly implementation dependent. This means if you require + * cleaning up expired sessions, you are responsible for cleaning up the expired + * sessions. + *

+ * + *

+ * The following is provided for you with the base configuration: + *

+ * + * + * + * @author Rob Winch + * @since 1.0 + */ +@Retention(value = java.lang.annotation.RetentionPolicy.RUNTIME) +@Target(value = { java.lang.annotation.ElementType.TYPE }) +@Documented +@Import(SpringHttpSessionConfiguration.class) +@Configuration +public @interface EnableSpringHttpSession { +} \ No newline at end of file diff --git a/spring-session/src/main/java/org/springframework/session/config/annotation/web/http/SpringHttpSessionConfiguration.java b/spring-session/src/main/java/org/springframework/session/config/annotation/web/http/SpringHttpSessionConfiguration.java new file mode 100644 index 00000000..e89df314 --- /dev/null +++ b/spring-session/src/main/java/org/springframework/session/config/annotation/web/http/SpringHttpSessionConfiguration.java @@ -0,0 +1,113 @@ +/* + * Copyright 2002-2015 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. + */ +package org.springframework.session.config.annotation.web.http; + +import java.util.ArrayList; +import java.util.List; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpSessionListener; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.session.ExpiringSession; +import org.springframework.session.SessionRepository; +import org.springframework.session.events.SessionCreatedEvent; +import org.springframework.session.events.SessionDestroyedEvent; +import org.springframework.session.web.http.HttpSessionStrategy; +import org.springframework.session.web.http.SessionEventHttpSessionListenerAdapter; +import org.springframework.session.web.http.SessionRepositoryFilter; + +/** + * Configures the basics for setting up Spring Session in a web environment. In + * order to use it, you must provide a {@link SessionRepository}. For example: + * + *
+ * {@literal @Configuration}
+ * {@literal @EnableSpringHttpSession}
+ * public class SpringHttpSessionConfig {
+ *
+ *     {@literal @Bean}
+ *     public MapSessionRepository sessionRepository() {
+ *         return new MapSessionRepository();
+ *     }
+ *
+ * }
+ * 
+ * + *

+ * It is important to note that no infrastructure for session expirations is + * configured for you out of the box. This is because things like session + * expiration are highly implementation dependent. This means if you require + * cleaning up expired sessions, you are responsible for cleaning up the expired + * sessions. + *

+ * + *

+ * The following is provided for you with the base configuration: + *

+ * + * + * + * @author Rob Winch + * @since 1.1 + * + * @see EnableSpringHttpSession + */ +@Configuration +@EnableScheduling +public class SpringHttpSessionConfiguration { + + private HttpSessionStrategy httpSessionStrategy; + + private List httpSessionListeners = new ArrayList(); + + @Bean + public SessionEventHttpSessionListenerAdapter sessionEventHttpSessionListenerAdapter() { + return new SessionEventHttpSessionListenerAdapter(httpSessionListeners); + } + + @Bean + public SessionRepositoryFilter springSessionRepositoryFilter(SessionRepository sessionRepository, ServletContext servletContext) { + SessionRepositoryFilter sessionRepositoryFilter = new SessionRepositoryFilter(sessionRepository); + sessionRepositoryFilter.setServletContext(servletContext); + if(httpSessionStrategy != null) { + sessionRepositoryFilter.setHttpSessionStrategy(httpSessionStrategy); + } + return sessionRepositoryFilter; + } + + @Autowired(required = false) + public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) { + this.httpSessionStrategy = httpSessionStrategy; + } + + @Autowired(required = false) + public void setHttpSessionListeners(List listeners) { + this.httpSessionListeners = listeners; + } +} diff --git a/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSession.java b/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSession.java index 5803df1d..c13dbe95 100644 --- a/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSession.java +++ b/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/EnableRedisHttpSession.java @@ -22,6 +22,7 @@ import java.lang.annotation.Target; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession; /** * Add this annotation to an {@code @Configuration} class to expose the @@ -29,6 +30,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory; * backed by Redis. In order to leverage the annotation, a single {@link RedisConnectionFactory} * must be provided. For example: *
+ * 
  * {@literal @Configuration}
  * {@literal @EnableRedisHttpSession}
  * public class RedisHttpSessionConfig {
@@ -39,12 +41,14 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
  *     }
  *
  * }
+ * 
  * 
* * More advanced configurations can extend {@link RedisHttpSessionConfiguration} instead. * * @author Rob Winch * @since 1.0 + * @see EnableSpringHttpSession */ @Retention(value=java.lang.annotation.RetentionPolicy.RUNTIME) @Target(value={java.lang.annotation.ElementType.TYPE}) diff --git a/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java b/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java index 11be1ea2..6bc3d202 100644 --- a/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java +++ b/spring-session/src/main/java/org/springframework/session/data/redis/config/annotation/web/http/RedisHttpSessionConfiguration.java @@ -15,14 +15,9 @@ */ package org.springframework.session.data.redis.config.annotation.web.http; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import java.util.Map; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpSessionListener; - import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; @@ -42,13 +37,10 @@ import org.springframework.data.redis.listener.PatternTopic; import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.session.ExpiringSession; -import org.springframework.session.SessionRepository; +import org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration; import org.springframework.session.data.redis.RedisOperationsSessionRepository; import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction; import org.springframework.session.data.redis.config.ConfigureRedisAction; -import org.springframework.session.web.http.HttpSessionStrategy; -import org.springframework.session.web.http.SessionEventHttpSessionListenerAdapter; import org.springframework.session.web.http.SessionRepositoryFilter; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; @@ -65,25 +57,16 @@ import org.springframework.util.StringUtils; */ @Configuration @EnableScheduling -public class RedisHttpSessionConfiguration implements ImportAware, BeanClassLoaderAware { +public class RedisHttpSessionConfiguration extends SpringHttpSessionConfiguration implements ImportAware, BeanClassLoaderAware { private ClassLoader beanClassLoader; private Integer maxInactiveIntervalInSeconds = 1800; - private HttpSessionStrategy httpSessionStrategy; - private ConfigureRedisAction configureRedisAction = new ConfigureNotifyKeyspaceEventsAction(); - private List httpSessionListeners = new ArrayList(); - private String redisNamespace = ""; - @Bean - public SessionEventHttpSessionListenerAdapter sessionEventHttpSessionListenerAdapter() { - return new SessionEventHttpSessionListenerAdapter(httpSessionListeners); - } - @Bean public RedisMessageListenerContainer redisMessageListenerContainer( RedisConnectionFactory connectionFactory, RedisOperationsSessionRepository messageListener) { @@ -118,16 +101,6 @@ public class RedisHttpSessionConfiguration implements ImportAware, BeanClassLoad return sessionRepository; } - @Bean - public SessionRepositoryFilter springSessionRepositoryFilter(SessionRepository sessionRepository, ServletContext servletContext) { - SessionRepositoryFilter sessionRepositoryFilter = new SessionRepositoryFilter(sessionRepository); - sessionRepositoryFilter.setServletContext(servletContext); - if(httpSessionStrategy != null) { - sessionRepositoryFilter.setHttpSessionStrategy(httpSessionStrategy); - } - return sessionRepositoryFilter; - } - public void setMaxInactiveIntervalInSeconds(int maxInactiveIntervalInSeconds) { this.maxInactiveIntervalInSeconds = maxInactiveIntervalInSeconds; } @@ -164,16 +137,6 @@ public class RedisHttpSessionConfiguration implements ImportAware, BeanClassLoad this.redisNamespace = enableAttrs.getString("redisNamespace"); } - @Autowired(required = false) - public void setHttpSessionStrategy(HttpSessionStrategy httpSessionStrategy) { - this.httpSessionStrategy = httpSessionStrategy; - } - - @Autowired(required = false) - public void setHttpSessionListeners(List listeners) { - this.httpSessionListeners = listeners; - } - @Bean public InitializingBean enableRedisKeyspaceNotificationsInitializer(RedisConnectionFactory connectionFactory) { return new EnableRedisKeyspaceNotificationsInitializer(connectionFactory, configureRedisAction);