diff --git a/docs/src/docs/asciidoc/guides/httpsession-xml.adoc b/docs/src/docs/asciidoc/guides/httpsession-xml.adoc new file mode 100644 index 00000000..a410d62a --- /dev/null +++ b/docs/src/docs/asciidoc/guides/httpsession-xml.adoc @@ -0,0 +1,170 @@ += Spring Session - HttpSession (Quick Start) +Rob Winch +:toc: + +This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` with XML based configuration. + +NOTE: The completed guide can be found in the <>. + +== Updating Dependencies +Before you use Spring Session, you must ensure to update your dependencies. +If you are using Maven, ensure to add the following dependencies: + +.pom.xml +[source,xml] +[subs="verbatim,attributes"] +---- + + + + + org.springframework.session + spring-session-data-redis + {spring-session-version} + pom + + + org.springframework + spring-web + {spring-version} + + +---- + +ifeval::["{version-snapshot}" == "true"] +Since we are using a SNAPSHOT version, we need to ensure to add the Spring Snapshot Maven Repository. +Ensure you have the following in your pom.xml: + +.pom.xml +[source,xml] +---- + + + + + + spring-snapshot + https://repo.spring.io/libs-snapshot + + +---- +endif::[] + +ifeval::["{version-milestone}" == "true"] +Since We are using a Milestone version, we need to ensure to add the Spring Milestone Maven Repository. +Ensure you have the following in your pom.xml: + +.pom.xml +[source,xml] +---- + + spring-milestone + https://repo.spring.io/libs-milestone + +---- +endif::[] + +// tag::config[] + +[[httpsession-xml-spring-configuration]] +== Spring XML Configuration + +After adding the required dependencies, we can create our Spring configuration. +The Spring configuration is responsible for creating a Servlet Filter that replaces the `HttpSession` implementation with an implementation backed by Spring Session. +Add the following Spring Configuration: + +.src/main/webapp/WEB-INF/spring/session.xml +[source,xml,indent=0] +---- +include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/spring/session.xml[tags=beans] +---- + +<1> We create an embedded Redis Server so that there is no need to start up Redis external of our application. +In a production application this is not necessary since we would point our connection to an external Redis instance. +<2> We use the combination of `` and `RedisHttpSessionConfiguration` because Spring Session does not yet provide XML Namespace support (see https://github.com/spring-projects/spring-session/issues/104[gh-104]). +This creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter. +The filter is what is in charge of replacing the `HttpSession` implementation to be backed by Spring Session. +In this instance Spring Session is backed by Redis. +<3> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server. +We use a http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#xsd-config-body-schemas-context-pphc[PropertyPlaceholderConfigurer] to externalize the port location. +For more information on configuring Spring Data Redis, refer to the http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation]. + +== XML Servlet Container Initialization + +Our <> created a Spring Bean named `springSessionRepositoryFilter` that implements `Filter`. +The `springSessionRepositoryFilter` bean is responsible for replacing the `HttpSession` with a custom implementation that is backed by Spring Session. + +In order for our `Filter` to do its magic, we need to instruct Spring to load our `session.xml` configuration. +We do this with the following configuration: + + +.src/main/webapp/WEB-INF/web.xml +[source,xml,indent=0] +---- +include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/web.xml[tags=context-param] +include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/web.xml[tags=listeners] +---- + +The http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener] reads the contextConfigLocation and picks up our session.xml configuration. + +Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request. +The following snippet performs this last step for us: + +.src/main/webapp/WEB-INF/web.xml +[source,xml,indent=0] +---- +include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/web.xml[tags=springSessionRepositoryFilter] +---- + +The http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy] will look up a Bean by the name of `springSessionRepositoryFilter` and cast it to a `Filter`. +For every request that `DelegatingFilterProxy` is invoked, the `springSessionRepositoryFilter` will be invoked. + +// end::config[] + +[[httpsession-xml-sample]] +== httpsession-xml Sample Application + +=== Running the httpsession-xml Sample Application + +You can run the sample by obtaining the {download-url}[source code] and invoking the following command: + +---- +$ ./gradlew :samples:httpsession-xml:tomcatRun +---- + +You should now be able to access the application at http://localhost:8080/ + +=== Exploring the httpsession-xml Sample Application + +Try using the application. Fill out the form with the following information: + +* **Attribute Name:** _username_ +* **Attribute Value:** _rob_ + +Now click the **Set Attribute** button. You should now see the values displayed in the table. + +=== How does it work? + +We interact with the standard `HttpSession` in the `SessionServlet` shown below: + +.src/main/java/sample/SessionServlet.java +[source,java] +---- +include::{samples-dir}httpsession-xml/src/main/java/sample/SessionServlet.java[tags=class] +---- + +Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis. +Spring Session creates a cookie named SESSION in your browser that contains the id of your session. +Go ahead and view the cookies (click for help with https://developer.chrome.com/devtools/docs/resources#cookies[Chrome] or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]). + +If you like, you can easily remove the session using redis-cli. For example, on a Linux based system you can type: + + $ redis-cli keys '*' | xargs redis-cli del + +TIP: The Redis documentation has instructions for http://redis.io/topics/quickstart[installing redis-cli]. + +Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie: + + $ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e + +Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed. \ No newline at end of file diff --git a/docs/src/docs/asciidoc/index.adoc b/docs/src/docs/asciidoc/index.adoc index a451b18c..0b1b20dd 100644 --- a/docs/src/docs/asciidoc/index.adoc +++ b/docs/src/docs/asciidoc/index.adoc @@ -37,7 +37,7 @@ If you are looking to get started with Spring Session, the best place to start i | {gh-samples-url}httpsession-xml[HttpSession XML] | Demonstrates how to use Spring Session to replace the `HttpSession` with a Redis store using XML based configuration. -| TBD +| link:guides/httpsession-xml.html[HttpSession XML Guide] | {gh-samples-url}boot[Spring Boot] | Demonstrates how to use Spring Session with Spring Boot. @@ -85,11 +85,30 @@ We have already mentioned that Spring Session provides transparent integration w === HttpSession with Redis Using Spring Session with `HttpSession` is enabled by adding a Servlet Filter before anything that uses the `HttpSession`. +You can choose from enabling this using either: -NOTE: The <> provides a working sample on how to integrate Spring Session and `HttpSession`. +* <> +* <> + +[[httpsession-redis-jc]] +==== Redis Java Based Configuration + +This section describes how to use Redis to back `HttpSession` using Java based configuration. + +NOTE: The <> provides a working sample on how to integrate Spring Session and `HttpSession` using XML configuration. You can read the basic steps for integration below, but you are encouraged to follow along with the detailed HttpSession Guide when integrating with your own application. -include::guides/httpsession.adoc[tags=config,leveloffset=+2] +include::guides/httpsession.adoc[tags=config,leveloffset=+3] + +[[httpsession-redis-xml]] +==== Redis XML Based Configuration + +This section describes how to use Redis to back `HttpSession` using XML based configuration. + +NOTE: The <> provides a working sample on how to integrate Spring Session and `HttpSession` using XML configuration. +You can read the basic steps for integration below, but you are encouraged to follow along with the detailed HttpSession XML Guide when integrating with your own application. + +include::guides/httpsession-xml.adoc[tags=config,leveloffset=+3] [[httpsession-how]] === How HttpSession Integration Works @@ -135,7 +154,7 @@ public class SessionRepositoryFilter implements Filter { public doFilter(ServletRequest request, ServletResponse response, FilterChain chain) { HttpServletRequest httpRequest = (HttpServletRequest) request; SessionRepositoryRequestWrapper customRequest = - new SessionRepositoryRequestWrapper(httpRequest); + new SessionRepositoryRequestWrapper(httpRequest); chain.doFilter(customRequest, response, chain); } @@ -287,8 +306,8 @@ Each session is set and updated using the HMSET command. An example of how each session is stored can be seen below. HMSET spring:session:sessions: creationTime 1404360000000 \ - maxInactiveInterval 1800 lastAccessedTime 1404360000000 \ - sessionAttr: someAttrValue sessionAttr: someAttrValue2 + maxInactiveInterval 1800 lastAccessedTime 1404360000000 \ + sessionAttr: someAttrValue sessionAttr: someAttrValue2 [[api-redisoperationssessionrepository-expiration]] ===== Session Expiration diff --git a/samples/httpsession-xml/src/main/webapp/WEB-INF/spring/session.xml b/samples/httpsession-xml/src/main/webapp/WEB-INF/spring/session.xml index 250c72bc..b711a0cc 100644 --- a/samples/httpsession-xml/src/main/webapp/WEB-INF/spring/session.xml +++ b/samples/httpsession-xml/src/main/webapp/WEB-INF/spring/session.xml @@ -6,13 +6,15 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> + + - - + - - + + + \ No newline at end of file diff --git a/samples/httpsession-xml/src/main/webapp/WEB-INF/web.xml b/samples/httpsession-xml/src/main/webapp/WEB-INF/web.xml index ad259395..7e46aa5b 100644 --- a/samples/httpsession-xml/src/main/webapp/WEB-INF/web.xml +++ b/samples/httpsession-xml/src/main/webapp/WEB-INF/web.xml @@ -6,31 +6,38 @@ - Location of the XML file that defines the root application context - Applied by ContextLoaderListener. --> + contextConfigLocation /WEB-INF/spring/*.xml + + springSessionRepositoryFilter org.springframework.web.filter.DelegatingFilterProxy - springSessionRepositoryFilter /* + + - org.springframework.web.context.ContextLoaderListener + + org.springframework.web.context.ContextLoaderListener + + session