Compare commits

..

5 Commits

Author SHA1 Message Date
Spring Buildmaster
b53e52f529 Release version 1.1.1.RELEASE 2016-03-16 08:15:00 -07:00
Rob Winch
debaea0b58 Update New in 1.1 Doc
Fixes gh-390
2016-03-10 10:08:59 -06:00
Rob Winch
f8707009bd Delete refactor from findbyusername doc
Fixes gh-389
2016-03-10 10:05:07 -06:00
Rob Winch
47d897c846 DefaultCookieSerializer ignores null Cookie value
Previously a null Cookie value was returned by DefaultCookieSerializer
readCookieValues(). This could cause NullPointerExeptions later on.

This commit ignores cookies with a null value.

Fixes gh-392
2016-03-04 10:23:16 -06:00
Rob Winch
09d7704c9e Fix GemFire compile in Eclipse
Fixes gh-399
2016-02-29 14:38:54 -06:00
491 changed files with 44056 additions and 18597 deletions

View File

@@ -1,3 +0,0 @@
<!--
Thanks for raising a Spring Session issue. Please provide a brief description of your problem along with the version of Spring Session that you are using. If possible, please also consider putting together a sample application that reproduces the issue.
-->

View File

@@ -1,3 +0,0 @@
<!--
Thanks for contributing to Spring Session. Please provide a brief description of your pull-request and reference any related issue numbers (prefix references with #).
-->

2
.gitignore vendored
View File

@@ -10,5 +10,3 @@ target
out
.springBeans
*.rdb
!eclispe/.checkstyle
.checkstyle

View File

@@ -1,19 +0,0 @@
language: java
services:
- redis-server
jdk:
- oraclejdk8
os:
- linux
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
cache:
directories:
- $HOME/.gradle/caches/
- $HOME/.gradle/wrapper/
script: ./gradlew build

View File

@@ -40,5 +40,5 @@ appropriate to the circumstances. Maintainers are obligated to maintain confiden
with regard to the reporter of an incident.
This Code of Conduct is adapted from the
https://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
https://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]
http://contributor-covenant.org[Contributor Covenant], version 1.3.0, available at
http://contributor-covenant.org/version/1/3/0/[contributor-covenant.org/version/1/3/0/]

View File

@@ -10,8 +10,8 @@ By participating, you are expected to uphold this code. Please report unaccepta
== Using GitHub issues
We use GitHub issues to track bugs and enhancements. If you have a general usage question
please ask on https://stackoverflow.com[Stack Overflow]. The Spring Session team and the
broader community monitor the https://stackoverflow.com/tags/spring-session[`spring-session`]
please ask on http://stackoverflow.com[Stack Overflow]. The Spring Session team and the
broader community monitor the http://stackoverflow.com/tags/spring-session[`spring-session`]
tag.
If you are reporting a bug, please help to speed up problem diagnosis by providing as much
@@ -21,6 +21,12 @@ reproduces the problem.
== Sign the Contributor License Agreement
If you have not previously done so, please fill out and
submit the https://cla.pivotal.io/sign/spring[Contributor License Agreement].
Before we accept a non-trivial patch or pull request we will need you to sign the
https://support.springsource.com/spring_committer_signup[contributor's agreement].
If you have previously signed the CLA for any project, there is no need to sign up again.
Signing the contributor's agreement does not grant anyone commit rights to the main
repository, but it does mean that we can accept your contributions, and you will get an
author credit if we do. Active contributors might be asked to join the core team, and
given the ability to merge pull requests. Use the project `Spring Security` (the parent project)
and '`Rob Winch`' in the project lead field when you complete the form.

View File

@@ -1,7 +1,5 @@
image:https://badges.gitter.im/spring-projects/spring-session.svg[link="https://gitter.im/spring-projects/spring-session?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
image:https://travis-ci.org/spring-projects/spring-session.svg?branch=master["Build Status", link="https://travis-ci.org/spring-projects/spring-session"]
= Spring Session
Rob Winch
@@ -19,8 +17,8 @@ By participating, you are expected to uphold this code. Please report unaccepta
= Spring Session Project Site
You can find the documentation, issue management, support, samples, and guides for using Spring Session at https://projects.spring.io/spring-session/
You can find the documentation, issue management, support, samples, and guides for using Spring Session at http://projects.spring.io/spring-session/
= License
Spring Session is Open Source software released under the https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
Spring Session is Open Source software released under the http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].

View File

@@ -12,18 +12,12 @@ buildscript {
}
}
plugins {
id "org.sonarqube" version "1.2"
}
group = 'org.springframework.session'
ext.springBootVersion = '1.3.2.RELEASE'
ext.IDE_GRADLE = "$rootDir/gradle/ide.gradle"
ext.JAVA_GRADLE = "$rootDir/gradle/java.gradle"
ext.SPRING3_GRADLE = "$rootDir/gradle/spring3.gradle"
ext.MAVEN_GRADLE = "$rootDir/gradle/publish-maven.gradle"
ext.SAMPLE_GRADLE = "$rootDir/gradle/sample.gradle"
ext.TOMCAT_GRADLE = "$rootDir/gradle/tomcat.gradle"
ext.TOMCAT_6_GRADLE = "$rootDir/gradle/tomcat6.gradle"
ext.TOMCAT_7_GRADLE = "$rootDir/gradle/tomcat7.gradle"
@@ -32,11 +26,12 @@ ext.releaseBuild = version.endsWith('RELEASE')
ext.snapshotBuild = version.endsWith('SNAPSHOT')
ext.milestoneBuild = !(releaseBuild || snapshotBuild)
apply plugin: 'sonar-runner'
apply plugin: 'base'
sonarqube {
properties {
sonarRunner {
sonarProperties {
property "sonar.java.coveragePlugin", "jacoco"
property "sonar.projectName", "Spring Session"
property "sonar.jacoco.reportPath", "${buildDir.name}/jacoco.exec"

View File

@@ -1,166 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
"https://www.puppycrawl.com/dtds/configuration_1_3.dtd">
<module name="Checker">
<!-- Suppressions -->
<module name="SuppressionFilter">
<property name="file" value="${configDir}/suppressions.xml"/>
</module>
<!-- Root Checks -->
<module name="RegexpHeader">
<property name="headerFile" value="${configDir}/header.txt"/>
<property name="fileExtensions" value="java"/>
</module>
<module name="NewlineAtEndOfFile">
<property name="lineSeparator" value="lf"/>
<property name="fileExtensions" value="java,xml"/>
</module>
<!-- TreeWalker Checks -->
<module name="TreeWalker">
<!-- Annotations -->
<module name="AnnotationUseStyle">
<property name="elementStyle" value="compact"/>
</module>
<module name="MissingOverride"/>
<module name="PackageAnnotation"/>
<module name="AnnotationLocation">
<property name="allowSamelineSingleParameterlessAnnotation" value="false" />
</module>
<!-- Block Checks -->
<module name="EmptyBlock">
<property name="option" value="text"/>
</module>
<module name="LeftCurly"/>
<module name="RightCurly">
<property name="option" value="alone"/>
</module>
<module name="NeedBraces"/>
<module name="AvoidNestedBlocks"/>
<!-- Class Design -->
<module name="FinalClass"/>
<module name="InterfaceIsType"/>
<module name="HideUtilityClassConstructor"/>
<module name="MutableException"/>
<module name="InnerTypeLast"/>
<module name="OneTopLevelClass"/>
<!-- Coding -->
<module name="CovariantEquals"/>
<module name="EmptyStatement"/>
<module name="EqualsHashCode"/>
<module name="InnerAssignment"/>
<module name="SimplifyBooleanExpression"/>
<module name="SimplifyBooleanReturn"/>
<module name="StringLiteralEquality"/>
<module name="NestedForDepth">
<property name="max" value="3"/>
</module>
<module name="NestedIfDepth">
<property name="max" value="3"/>
</module>
<module name="NestedTryDepth">
<property name="max" value="3"/>
</module>
<module name="MultipleVariableDeclarations"/>
<module name="RequireThis">
<property name="checkMethods" value="false"/>
</module>
<module name="OneStatementPerLine"/>
<!-- Imports -->
<module name="AvoidStarImport"/>
<module name="AvoidStaticImport">
<property name="excludes"
value="org.assertj.core.api.Assertions.*, org.mockito.Mockito.*, org.mockito.BDDMockito.*, org.mockito.AdditionalMatchers.*, org.mockito.Matchers.*, org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*, org.springframework.test.web.servlet.result.MockMvcResultHandlers.*, org.springframework.test.web.servlet.result.MockMvcResultMatchers.*, org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*, org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.*, org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo"/>
</module>
<module name="IllegalImport"/>
<module name="RedundantImport"/>
<module name="UnusedImports">
<property name="processJavadoc" value="true"/>
</module>
<module name="ImportOrder">
<property name="groups" value="java,/^javax?\./,*,org.springframework"/>
<property name="ordered" value="true"/>
<property name="separated" value="true"/>
<property name="option" value="bottom"/>
<property name="sortStaticImportsAlphabetically" value="true"/>
</module>
<!-- Javadoc Comments -->
<module name="JavadocType">
<property name="scope" value="package"/>
<property name="authorFormat" value=".+\s.+"/>
</module>
<module name="JavadocMethod">
<property name="allowMissingJavadoc" value="true"/>
</module>
<module name="JavadocVariable">
<property name="scope" value="public"/>
</module>
<module name="JavadocStyle">
<property name="checkEmptyJavadoc" value="true"/>
</module>
<module name="NonEmptyAtclauseDescription"/>
<module name="JavadocTagContinuationIndentation">
<property name="offset" value="0"/>
</module>
<module name="AtclauseOrder">
<property name="target" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF"/>
<property name="tagOrder" value="@param, @author, @since, @see, @version, @serial, @deprecated"/>
</module>
<module name="AtclauseOrder">
<property name="target" value="METHOD_DEF, CTOR_DEF, VARIABLE_DEF"/>
<property name="tagOrder" value="@param, @return, @throws, @since, @deprecated, @see"/>
</module>
<!-- Miscellaneous -->
<module name="CommentsIndentation"/>
<module name="UpperEll"/>
<module name="ArrayTypeStyle"/>
<module name="OuterTypeFilename"/>
<!-- Modifiers -->
<module name="RedundantModifier"/>
<!-- Regexp -->
<module name="RegexpSinglelineJava">
<property name="format" value="^\t* +\t*\S"/>
<property name="message" value="Line has leading space characters; indentation should be performed with tabs only."/>
<property name="ignoreComments" value="true"/>
</module>
<module name="RegexpSinglelineJava">
<property name="maximum" value="0"/>
<property name="format" value="org\.mockito\.Mockito\.(when|doThrow|doAnswer)"/>
<property name="message"
value="Please use BDDMockto imports."/>
<property name="ignoreComments" value="true"/>
</module>
<module name="RegexpSinglelineJava">
<property name="maximum" value="0"/>
<property name="format" value="org\.junit\.Assert\.assert"/>
<property name="message" value="Please use AssertJ imports."/>
<property name="ignoreComments" value="true"/>
</module>
<module name="Regexp">
<property name="format" value="[ \t]+$"/>
<property name="illegalPattern" value="true"/>
<property name="message" value="Trailing whitespace"/>
</module>
<!-- Whitespace -->
<module name="GenericWhitespace"/>
<module name="MethodParamPad"/>
<module name="NoWhitespaceAfter">
<property name="tokens" value="BNOT, DEC, DOT, INC, LNOT, UNARY_MINUS, UNARY_PLUS, ARRAY_DECLARATOR"/>
</module>
<module name="NoWhitespaceBefore"/>
<module name="ParenPad"/>
<module name="TypecastParenPad"/>
<module name="WhitespaceAfter"/>
<module name="WhitespaceAround"/>
</module>
</module>

View File

@@ -1,16 +0,0 @@
^\Q/*\E$
^\Q * Copyright 2014-\E20\d\d\Q the original author or authors.\E$
^\Q *\E$
^\Q * Licensed under the Apache License, Version 2.0 (the "License");\E$
^\Q * you may not use this file except in compliance with the License.\E$
^\Q * You may obtain a copy of the License at\E$
^\Q *\E$
^\Q * https://www.apache.org/licenses/LICENSE-2.0\E$
^\Q *\E$
^\Q * Unless required by applicable law or agreed to in writing, software\E$
^\Q * distributed under the License is distributed on an "AS IS" BASIS,\E$
^\Q * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\E$
^\Q * See the License for the specific language governing permissions and\E$
^\Q * limitations under the License.\E$
^\Q */\E$
^.*$

View File

@@ -1,18 +0,0 @@
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC "-//Puppy Crawl//DTD Suppressions 1.1//EN"
"https://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
<suppressions>
<suppress files=".+Application\.java" checks="HideUtilityClassConstructor"/>
<suppress files=".+Configuration\.java" checks="HideUtilityClassConstructor"/>
<suppress files="[\\/]src[\\/]test[\\/]java[\\/]" checks="Javadoc"/>
<suppress files="[\\/]src[\\/]integration-test[\\/]java[\\/]" checks="Javadoc"/>
<suppress files="[\\/]docs[\\/]" checks="Javadoc"/>
<suppress files="[\\/]docs[\\/]" checks="CommentsIndentation"/>
<suppress files="[\\/]docs[\\/]" checks="InnerTypeLast"/>
<suppress files="[\\/]samples[\\/]" checks="Javadoc"/>
<suppress files="[\\/]samples[\\/]" checks="CommentsIndentation"/>
<suppress files="[\\/]samples[\\/]" checks="InnerTypeLast"/>
</suppressions>

View File

@@ -28,13 +28,11 @@ tasks.findByPath("artifactoryPublish")?.enabled = false
dependencies {
testCompile project(':spring-session'),
project(':spring-session-data-mongo'),
"org.springframework.data:spring-data-gemfire:$springDataGemFireVersion",
"org.springframework.data:spring-data-redis:$springDataRedisVersion",
"org.springframework.data:spring-data-gemfire:$springDataGemFireVersion",
"org.springframework:spring-websocket:${springVersion}",
"org.springframework:spring-messaging:${springVersion}",
"org.springframework:spring-jdbc:${springVersion}",
"org.springframework.security:spring-security-web:${springSecurityVersion}",
"org.springframework.security:spring-security-test:${springSecurityVersion}",
'junit:junit:4.11',
@@ -62,7 +60,6 @@ asciidoctor {
'docs-test-dir' : rootProject.projectDir.path + '/docs/src/test/java/',
'docs-test-resources-dir' : rootProject.projectDir.path + '/docs/src/test/resources/',
'samples-dir' : rootProject.projectDir.path + '/samples/',
'session-main-resources-dir' : rootProject.projectDir.path + '/spring-session/src/main/resources/',
'source-highlighter' : 'coderay',
'imagesdir':'./images',

View File

@@ -93,7 +93,7 @@ spring.redis.password=secret
spring.redis.port=6379
----
For more information, refer to https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-connecting-to-redis[Connecting to Redis] portion of the Spring Boot documentation.
For more information, refer to http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-connecting-to-redis[Connecting to Redis] portion of the Spring Boot documentation.
[[boot-servlet-configuration]]
== Servlet Container Initialization
@@ -117,7 +117,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
@@ -153,7 +153,7 @@ If you like, you can easily remove the session using redis-cli. For example, on
$ redis-cli keys '*' | xargs redis-cli del
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
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:

View File

@@ -27,7 +27,7 @@ This allows sharing a session across domains and applications.
If the regular expression does not match, no domain is set and the existing domain will be used.
If the regular expression matches, the first https://docs.oracle.com/javase/tutorial/essential/regex/groups.html[grouping] will be used as the domain.
This means that a request to https://child.example.com will set the domain to example.com.
However, a request to http://localhost:8080/ or https://192.168.1.100:8080/ will leave the cookie unset and thus still work in development without any changes necessary for production.
However, a request to http://localhost:8080/ or http://192.168.1.100:8080/ will leave the cookie unset and thus still work in development without any changes necessary for production.
[WARNING]
====
@@ -78,7 +78,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====

View File

@@ -6,9 +6,6 @@ This guide describes how to use Spring Session to find sessions by username.
NOTE: The completed guide can be found in the <<findbyusername-sample, findbyusername application>>.
NOTE: This feature will likely be refactored in the next release to account for https://github.com/spring-projects/spring-session/issues/301[#301]
[[findbyusername-assumptions]]
== Assumptions
@@ -110,7 +107,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====

View File

@@ -1,129 +0,0 @@
= Spring Session - Grails
Eric Helgeson
:toc:
This guide describes how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when using Grails 3.1
NOTE: Grails 3.1 is based off spring boot 1.3 so much of the advanced configuration and options can be found in the boot docs as well.
NOTE: The completed guide can be found in the <<grails3-sample, Grails 3 sample application>>.
== Updating Dependencies
Before you use Spring Session, you must ensure to update your dependencies.
We assume you are working with a working Grails 3.1 web profile.
Add the following dependencies:
.build.gradle
[source,groovy]
[subs="verbatim,attributes"]
----
dependencies {
compile 'org.springframework.boot:spring-boot-starter-redis'
compile 'org.springframework.session:spring-session:{spring-session-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:
.build.gradle
[source,groovy]
----
repositories {
maven {
url '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:
.build.gradle
[source,groovy]
----
repositories {
maven {
url 'https://repo.spring.io/libs-milestone'
}
}
----
endif::[]
[[grails3-redis-configuration]]
== Configuring the Redis Connection
Spring Boot automatically creates a `RedisConnectionFactory` that connects Spring Session to a Redis Server on localhost on port 6379 (default port).
In a production environment you need to ensure to update your configuration to point to your Redis server.
For example, you can include the following in your *application.yml*
.grails-app/conf/application.yml
[source,yml]
----
spring:
redis:
host: localhost
password: secret
port: 6397
----
For more information, refer to https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-connecting-to-redis[Connecting to Redis] portion of the Spring Boot documentation.
[[grails3-sample]]
== Grails 3 Sample Application
The Grails 3 Sample Application demonstrates how to use Spring Session to transparently leverage Redis to back a web application's `HttpSession` when using Grails.
[[grails3-running]]
=== Running the Grails 3 Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
----
$ ./gradlew :samples:grails3:bootRun
----
You should now be able to access the application at http://localhost:8080/test/index
[[grails3-explore]]
=== Exploring the security Sample Application
Try using the application. Enter the following to log in:
* **Username** _user_
* **Password** _password_
Now click the **Login** button.
You should now see a message indicating your are logged in with the user entered previously.
The user's information is stored in Redis rather than Tomcat's `HttpSession` implementation.
[[grails3-how]]
=== How does it work?
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis.
Spring Session replaces the `HttpSession` with an implementation that is backed by Redis.
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession` it is then persisted into Redis.
When a new `HttpSession` is created, 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 https://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/test/index and observe that we are no longer authenticated.

View File

@@ -81,7 +81,7 @@ The filter is what is in charge of replacing the `HttpSession` implementation to
In this instance Spring Session is backed by Hazelcast.
<2> We create a `HazelcastInstance` that connects Spring Session to Hazelcast.
By default, an embedded instance of Hazelcast is started and connected to by the application.
For more information on configuring Hazelcast, refer to the https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#hazelcast-configuration[reference documentation].
For more information on configuring Hazelcast, refer to the http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#hazelcast-configuration[reference documentation].
== Servlet Container Initialization
@@ -126,7 +126,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
====
Hazelcast will run in embedded mode with your application by default, but if you want to connect
to a stand alone instance instead, you can configure it by following the instructions in the
https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#hazelcast-configuration[reference documentation].
http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#hazelcast-configuration[reference documentation].
====
----
@@ -157,9 +157,9 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
=== Interact with the data store
If you like, you can remove the session using https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#hazelcast-java-client[a Java client],
https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#other-client-implementations[one of the other clients], or the
https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#management-center[management center].
If you like, you can remove the session using http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#hazelcast-java-client[a Java client],
http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#other-client-implementations[one of the other clients], or the
http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#management-center[management center].
==== Using the console
@@ -168,7 +168,7 @@ For example, using the management center console after connecting to your Hazelc
default> ns spring:session:sessions
spring:session:sessions> m.clear
TIP: The Hazelcast documentation has instructions for https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#executing-console-commands[the console].
TIP: The Hazelcast documentation has instructions for http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#executing-console-commands[the console].
Alternatively, you can also delete the explicit key. Enter the following into the console ensuring to replace `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie:
@@ -179,7 +179,7 @@ Now visit the application at http://localhost:8080/ and observe that we are no l
==== Using the REST API
As described in the other clients section of the documentation, there is a
https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#rest-client[REST API]
http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#rest-client[REST API]
provided by the Hazelcast node(s).
For example, you could delete an individual key as follows (replacing `7e8383a4-082c-4ffe-a4bc-c40fd3363c5e` with the value of your SESSION cookie):

View File

@@ -1,263 +0,0 @@
= Spring Session - HttpSession with GemFire Client/Server using Spring Boot
John Blum
:toc:
This guide describes how to build a _Spring Boot_ application configured with _Spring Session_ to transparently leverage
Pivotal GemFire to back a web application's `HttpSession`.
In this sample, GemFire's client/server topology is employed using a pair of _Spring Boot_ applications, one to
configure and run a GemFire Server and another to configure and run the client, Spring MVC-based web application
making use of the `HttpSession`.
NOTE: The completed guide can be found in the <<httpsession-gemfire-boot-sample,HttpSession with GemFire using Spring Boot Sample Application>>.
== Updating Dependencies
Before using _Spring Session_, you must ensure that the required dependencies are included.
If you are using Maven, include the following `dependencies` in your _pom.xml_:
.pom.xml
[source,xml]
[subs="verbatim,attributes"]
----
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-gemfire</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
----
ifeval::["{version-snapshot}" == "true"]
Since we are using a SNAPSHOT version, we need to add the Spring Snapshot Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
.pom.xml
[source,xml]
----
<repositories>
<!-- ... -->
<repository>
<id>spring-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
----
endif::[]
ifeval::["{version-milestone}" == "true"]
Since we are using a Milestone version, we need to add the Spring Milestone Maven Repository.
If you are using Maven, include the following `repository` declaration in your _pom.xml_:
.pom.xml
[source,xml]
----
<repositories>
<!-- ... -->
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
</repositories>
----
endif::[]
// tag::config[]
[[httpsession-spring-java-configuration]]
== Spring Boot Configuration
After adding the required dependencies and repository declarations, we can create our Spring configuration
for both the GemFire client and server using _Spring Boot_. The Spring configuration is responsible for
creating a Servlet Filter that replaces the `HttpSession` with an implementation backed by _Spring Session_
and GemFire.
=== Spring Boot-based GemFire Server
We start with the _Spring Boot_ application for configuring and bootstrapping a GemFire Server process...
[source,java]
----
include::{samples-dir}httpsession-gemfire-boot/src/main/java/sample/server/GemFireServer.java[tags=class]
----
<1> The `@EnableGemFireHttpSession` annotation is used on the GemFire Server mainly to define the corresponding
Region (e.g. `ClusteredSpringSessions`, the default) in which Session state information will be stored
and managed by GemFire. As well, we have specified an arbitrary expiration attribute (i.e. `maxInactiveIntervalInSeconds`)
for when the Session will timeout, which is triggered by a GemFire Region entry expiration event that also invalidates
the Session object in the Region.
<2> Next, we define a few `Properties` allowing us to configure certain aspects of the GemFire Server using
https://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System properties].
<3> Then, we create an instance of the GemFire Cache using our defined `Properties`.
<4> Finally, we setup a Cache Server instance running in the GemFire Server to listen for connections from cache clients.
The Cache Server `Socket` will be used to connect our GemFire client cache, _Spring Boot_ web application to the server.
The sample also makes use of a `PropertySourcesPlaceholderConfigurer` bean in order to externalize the sample application
configuration to affect GemFire and application configuration/behavior from the command-line (e.g. such as GemFire's
`log-level` using the `gemfire.log.level` System property; more details below).
=== Spring Boot-based GemFire cache client Web application
Now, we create the _Spring Boot_ web application (a GemFire cache client), exposing our Web service
using Spring MVC along with _Spring Session_ backed by GemFire, connected to our _Spring Boot_-based GemFire Server,
in order to manage Session state in a cluster/replicated-enabled fashion.
[source,java]
----
include::{samples-dir}httpsession-gemfire-boot/src/main/java/sample/client/Application.java[tags=class]
----
<1> Here, again, we use the `@EnableGemFireHttpSession` annotation to not only configure the GemFire cache client,
but also to override the (HTTP) Web application container's `HttpSession` and replace it with a Session implementation
backed by _Spring Session_ in conjunction with GemFire. Also notice, we did not define any Session expiration timeout
with the `maxInactiveIntervalInSeconds` attribute this time. That is because the Session expiration is managed
by GemFire, which will appropriately notify the cache client when the Session times out. Again, we have just resorted
to using the default Region, `ClusteredSpringSessions`. Of course, we can change the Region name, but we must do so
on both the client and the server. That is a GemFire requirement, not a _Spring Session Data GemFire_ requirement.
<2> Similary to the server configuration, we set a few basic GemFire System `Properties` on the client.
<3> Although, this time, an instance of `ClientCache` is created with the `ClientCacheFactoryBean` from _Spring Data GemFire_.
<4> However, in order to connect to the GemFire Server we must define a GemFire `Pool` bean containing pre-populated
connections to the server. Whenever a client Region entry operation corresponding to a Session update occurs,
the client-side Region will use an existing, pooled connection to route the operation to the server.
<5> The following _Spring_ `BeanPostProcessor` (along with some utility methods) are only needed for testing purposes
and is not required by any production code. Specifically, the `BeanPostProcessor` along with the code referenced in *6*
is useful in integration test cases where the client and server processes are forked by the test framework. It is pretty
easy to figure out that a race condition is imminent without proper coordination between the client and the server,
therefore, the BPP and `ClientMembershipListener` help sync the interaction between the client and the server
on startup during automated testing.
<6> See <5> above.
<7> Navigates the Web application to the home page (`index.html`), which uses **Thymeleaf** templates for server-side
pages.
<8> Heartbeat web service endpoint (useful for manual testing purposes).
<9> Web service endpoint for adding a Session attributes defined by the user using the Web application UI. In addition,
the webapp stores an additional Session attribute (`requestCount`) to keep track of how many HTTP requests the user
has sent during the current "session".
There are many other utility methods, so please refer to the actual source code for full details.
TIP: In typical GemFire deployments, where the cluster includes potentially hundreds or thousands of GemFire data nodes
(servers), it is more common for clients to connect to one or more GemFire Locators running in the cluster. A Locator
passes meta-data to clients about the servers available, their load and which servers have the client's data of interest,
which is particularly important in direct, single-hop data access and latency-sensitive operations. See more details
about the https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology in GemFire's User Guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
The `@EnableGemFireHttpSession` annotation enables a developer to configure certain aspects of both _Spring Session_
and GemFire out-of-the-box using the following attributes:
* `maxInactiveIntervalInSeconds` - controls _HttpSession_ idle-timeout expiration (defaults to **30 minutes**).
* `regionName` - specifies the name of the GemFire Region used to store `HttpSession` state (defaults is "*ClusteredSpringSessions*").
* `clientRegionShort` - specifies GemFire's https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policy]
with a GemFire https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
(default is `PROXY`). This attribute is only used when configuring client Region.
* `serverRegionShort` - specifies GemFire's https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policy]
using a GemFire https://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html[RegionShortcut]
(default is `PARTITION`). This attribute is only used when configuring server Regions, or when a p2p topology is employed.
NOTE: It is important to note that the GemFire client Region name must match a server Region by the same name if
the client Region is a `PROXY` or `CACHING_PROXY`. Client and server Region names are not required to match if
the client Region used to store Spring Sessions is `LOCAL`. However, keep in mind that your session state will not
be propagated to the server and you lose all the benefits of using GemFire to store and manage distributed, replicated
session state information in a cluster.
[[httpsession-gemfire-boot-sample]]
== HttpSession with GemFire using Spring Boot Sample Application
=== Running the httpsession-gemfire-boot Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following commands.
First, you must run the server:
----
$ ./gradlew :samples:httpsession-gemfire-boot:run [-Dgemfire.log-level=config]
----
Then, in a separate terminal, run the client:
----
$ ./gradlew :samples:httpsession-gemfire-boot:bootRun [-Dgemfire.log-level=config]
----
You should now be able to access the application at http://localhost:8080/. In this sample, the web application
is the client cache and the server is standalone.
=== Exploring the httpsession-gemfire-boot Sample Application
Try using the application. Fill out the form with the following information:
* **Attribute Name:** _username_
* **Attribute Value:** _test_
Now click the **Set Attribute** button. You should now see the attribute name and value displayed in the table
along with an additional attribute (`requestCount`) indicating the number of Session interactions (via HTTP requests).
=== How does it work?
We interact with the standard `HttpSession` in the the Spring MVC web service endpoint, shown here for convenience:
.src/main/java/sample/SessionServlet.java
[source,java]
----
@RequestMapping(method = RequestMethod.POST, path = "/session")
public String session(HttpSession session, ModelMap modelMap,
@RequestParam(name = "attributeName", required = false) String name,
@RequestParam(name = "attributeValue", required = false) String value) {
modelMap.addAttribute("sessionAttributes",
attributes(setAttribute(updateRequestCount(session), name, value)));
return INDEX_TEMPLATE_VIEW_NAME;
}
----
Instead of using the embedded HTTP server's `HttpSession`, we are actually persisting the Session state in GemFire.
_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]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
$ gfsh
Then, enter the following commands in _Gfsh_ ensuring to replace `70002719-3c54-4c20-82c3-e7faa6b718f3` with the value
of your SESSION cookie, or the session ID returned by the GemFire OQL query (which should match):
....
gfsh>connect --jmx-manager=localhost[1099]
gfsh>query --query='SELECT * FROM /ClusteredSpringSessions.keySet'
Result : true
startCount : 0
endCount : 20
Rows : 1
Result
------------------------------------
70002719-3c54-4c20-82c3-e7faa6b718f3
NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using https://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ again and observe that the attribute we added is no longer displayed.
Alternatively, you can wait **20 seconds** for the session to expire and timeout, and then refresh the page. The attribute
we added should no longer be displayed in the table.

View File

@@ -94,7 +94,7 @@ by Spring will be configured appropriately.
<5> Then, a Spring `BeanPostProcessor` is registered to determine whether a GemFire Server at the designated host/port
is running, blocking client startup until the server is available.
<6> Next, we include a `Properties` bean to configure certain aspects of the GemFire client cache using
https://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System properties].
http://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System properties].
In this case, we are just setting GemFire's `log-level` from a sample application-specific System property, defaulting
to `warning` if unspecified.
<7> Finally, we create the GemFire client cache and configure a Pool of client connections to talk to the GemFire Server
@@ -104,9 +104,9 @@ and so on. Also, our `Pool` has been configured to connect directly to a server.
TIP: In typical GemFire deployments, where the cluster includes potentially hundreds of GemFire data nodes (servers),
it is more common for clients to connect to one or more GemFire Locators running in the cluster. A Locator passes meta-data
to clients about the servers available, load and which servers have the client's data of interest, which is particularly
important for single-hop, direct data access. See more details about the https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology in GemFire's User Guide].
important for single-hop, direct data access. See more details about the http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology in GemFire's User Guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
=== Server Configuration
@@ -166,7 +166,7 @@ include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/webapp/WEB-I
include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/webapp/WEB-INF/web.xml[tags=listeners]
----
The https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener]
The http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener]
reads the `contextConfigLocation` context parameter value and picks up our _session-client.xml_ configuration file.
Finally, we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter`
@@ -180,7 +180,7 @@ The following snippet performs this last step for us:
include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/webapp/WEB-INF/web.xml[tags=springSessionRepositoryFilter]
----
The https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy]
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[]
@@ -233,7 +233,7 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
@@ -262,7 +262,7 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using https://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ again and observe that the attribute we added is no longer displayed.

View File

@@ -87,11 +87,11 @@ include::{samples-dir}httpsession-gemfire-clientserver/src/main/java/sample/Clie
implements `Filter`. The filter is what replaces the `HttpSession` with an implementation backed by Spring Session.
In this instance, Spring Session is backed by GemFire.
<2> Next, we register a `Properties` bean that allows us to configure certain aspects of the GemFire client cache
using https://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System properties].
using http://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System properties].
<3> Then, we configure a `Pool` of client connections to talk to the GemFire Server in our Client/Server topology. In our
configuration, we have used sensible settings for timeouts, number of connections and so on. Also, the `Pool` has been
configured to connect directly to a server. Learn more about various `Pool` configuration settings from the
https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html[PoolFactory API].
http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html[PoolFactory API].
<4> After configuring a `Pool`, we create an instance of the GemFire client cache using the GemFire `Properties`
and `Pool` to communicate with the server and perform cache data access operations.
<5> Finally, we include a Spring `BeanPostProcessor` to block the client until our GemFire Server is up and running,
@@ -105,7 +105,7 @@ time to startup.
The first approach uses a timed wait, checking at periodic intervals to determine whether a client `Socket` connection
can be made to the server's `CacheServer` endpoint.
The second approach uses a GemFire https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/management/membership/ClientMembershipListener.html[ClientMembershipListener]
The second approach uses a GemFire http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/management/membership/ClientMembershipListener.html[ClientMembershipListener]
that will be notified when the client has successfully connected to the server. Once a connection has been established,
the listener releases the latch that the `BeanPostProcessor` will wait on (up to the specified timeout) in the
`postProcessAfterInitialization` callback to block the client. Either one of these approaches are sufficient
@@ -115,17 +115,17 @@ in practice.
TIP: In typical GemFire deployments, where the cluster includes potentially hundreds of GemFire data nodes (servers),
it is more common for clients to connect to one or more GemFire Locators running in the cluster. A Locator passes meta-data
to clients about the servers available, load and which servers have the client's data of interest, which is particularly
important for single-hop, direct data access. See more details about the https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology in GemFire's User Guide].
important for single-hop, direct data access. See more details about the http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client/Server Topology in GemFire's User Guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
The `@EnableGemFireHttpSession` annotation enables a developer to configure certain aspects of both Spring Session
and GemFire out-of-the-box using the following attributes:
* `maxInactiveIntervalInSeconds` - controls HttpSession idle-timeout expiration (defaults to **30 minutes**).
* `regionName` - specifies the name of the GemFire Region used to store `HttpSession` state (defaults is "_ClusteredSpringSessions_").
* `clientRegionShort` - specifies GemFire https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policies]
with a GemFire https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
* `clientRegionShort` - specifies GemFire http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policies]
with a GemFire http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
(default is `PROXY`).
NOTE: It is important to note that the GemFire client Region name must match a server Region by the same name if
@@ -235,7 +235,7 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
@@ -264,7 +264,7 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using https://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ again and observe that the attribute we added is no longer displayed.

View File

@@ -100,7 +100,7 @@ Spring Session sample application.
TIP: Additionally, we have configured this data node (server) as a GemFire Manager as well using GemFire-specific
JMX System properties that enable JMX client (e.g. _Gfsh_) to connect to this running data node.
NOTE: For more information on configuring _Spring Data GemFire_, refer to the https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
== XML Servlet Container Initialization
@@ -118,7 +118,7 @@ include::{samples-dir}httpsession-gemfire-p2p-xml/src/main/webapp/WEB-INF/web.xm
include::{samples-dir}httpsession-gemfire-p2p-xml/src/main/webapp/WEB-INF/web.xml[tags=listeners]
----
The https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener]
The http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener]
reads the `contextConfigLocation` context parameter value and picks up our _session.xml_ configuration file.
Finally, we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter`
@@ -132,7 +132,7 @@ The following snippet performs this last step for us:
include::{samples-dir}httpsession-gemfire-p2p-xml/src/main/webapp/WEB-INF/web.xml[tags=springSessionRepositoryFilter]
----
The https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html[DelegatingFilterProxy]
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[]
@@ -176,7 +176,7 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
@@ -205,6 +205,6 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using https://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.

View File

@@ -96,15 +96,15 @@ Spring Session sample application.
TIP: Additionally, we have configured this data node (server) as a GemFire Manager as well using GemFire-specific
JMX System properties that enable JMX client (e.g. _Gfsh_) to connect to this running data node.
NOTE: For more information on configuring _Spring Data GemFire_, refer to the https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
NOTE: For more information on configuring _Spring Data GemFire_, refer to the http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/[reference guide].
The `@EnableGemFireHttpSession` annotation enables a developer to configure certain aspects of Spring Session
and GemFire out-of-the-box using the following attributes:
* `maxInactiveIntervalInSeconds` - controls HttpSession idle-timeout expiration (defaults to **30 minutes**).
* `regionName` - specifies the name of the GemFire Region used to store `HttpSession` state (defaults is "_ClusteredSpringSessions_").
* `serverRegionShort` - specifies GemFire https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policies]
with a GemFire https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html[RegionShortcut]
* `serverRegionShort` - specifies GemFire http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html[data management policies]
with a GemFire http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html[RegionShortcut]
(default is `PARTITION`).
NOTE: `clientRegionShort` is ignored in a peer cache configuration and only applies when a client-server topology,
@@ -175,7 +175,7 @@ Go ahead and view the cookies (click for help with https://developer.chrome.com/
or https://getfirebug.com/wiki/index.php/Cookies_Panel#Cookies_List[Firefox]).
NOTE: The following instructions assume you have a local GemFire installation. For more information on installation,
see https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
see http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
If you like, you can easily remove the session using `gfsh`. For example, on a Linux-based system type the following
at the command-line:
@@ -204,6 +204,6 @@ NEXT_STEP_NAME : END
gfsh>remove --region=/ClusteredSpringSessions --key="70002719-3c54-4c20-82c3-e7faa6b718f3"
....
NOTE: The _GemFire User Guide_ has more detailed instructions on using https://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
NOTE: The _GemFire User Guide_ has more detailed instructions on using http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html[gfsh].
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.

View File

@@ -1,152 +0,0 @@
= Spring Session - Spring Boot
Rob Winch, Vedran Pavić
:toc:
This guide describes how to use Spring Session to transparently leverage a relational database to back a web application's `HttpSession` when using Spring Boot.
NOTE: The completed guide can be found in the <<httpsession-jdbc-boot-sample, httpsession-jdbc-boot sample application>>.
== Updating Dependencies
Before you use Spring Session, you must ensure to update your dependencies.
We assume you are working with a working Spring Boot web application.
If you are using Maven, ensure to add the following dependencies:
.pom.xml
[source,xml]
[subs="verbatim,attributes"]
----
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>{spring-session-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
</dependencies>
----
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]
----
<repositories>
<!-- ... -->
<repository>
<id>spring-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
----
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]
----
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
----
endif::[]
// tag::config[]
[[httpsession-jdbc-boot-spring-configuration]]
== Spring 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:
[source,java]
----
include::{samples-dir}httpsession-jdbc-boot/src/main/java/sample/config/HttpSessionConfig.java[tags=class]
----
<1> The `@EnableJdbcHttpSession` annotation 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 a relational database.
[[httpsession-jdbc-boot-configuration]]
== Configuring the DataSource
Spring Boot automatically creates a `DataSource` that connects Spring Session to an embedded instance of H2 database.
In a production environment you need to ensure to update your configuration to point to your relational database.
For example, you can include the following in your *application.properties*
.src/main/resources/application.properties
----
spring.datasource.url=jdbc:postgresql://localhost:5432/myapp
spring.datasource.username=myapp
spring.datasource.password=secret
----
For more information, refer to https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-configure-datasource[Configure a DataSource] portion of the Spring Boot documentation.
[[httpsession-jdbc-boot-servlet-configuration]]
== Servlet Container Initialization
Our <<httpsession-jdbc-boot-spring-configuration,Spring Configuration>> 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, Spring needs to load our `Config` class.
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
Fortunately, Spring Boot takes care of both of these steps for us.
// end::config[]
[[httpsession-jdbc-boot-sample]]
== httpsession-jdbc-boot Sample Application
The httpsession-jdbc-boot Sample Application demonstrates how to use Spring Session to transparently leverage H2 database to back a web application's `HttpSession` when using Spring Boot.
[[httpsession-jdbc-boot-running]]
=== Running the httpsession-jdbc-boot Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
----
$ ./gradlew :samples:httpsession-jdbc-boot:bootRun
----
You should now be able to access the application at http://localhost:8080/
[[httpsession-jdbc-boot-explore]]
=== Exploring the security Sample Application
Try using the application. Enter the following to log in:
* **Username** _user_
* **Password** _password_
Now click the **Login** button.
You should now see a message indicating your are logged in with the user entered previously.
The user's information is stored in H2 database rather than Tomcat's `HttpSession` implementation.
[[httpsession-jdbc-boot-how]]
=== How does it work?
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in H2 database.
Spring Session replaces the `HttpSession` with an implementation that is backed by a relational database.
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession` it is then persisted into H2 database.
When a new `HttpSession` is created, 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 H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL)
Now visit the application at http://localhost:8080/ and observe that we are no longer authenticated.

View File

@@ -1,162 +0,0 @@
= Spring Session - HttpSession (Quick Start)
Rob Winch, Vedran Pavić
:toc:
This guide describes how to use Spring Session to transparently leverage a relational to back a web application's `HttpSession` with XML based configuration.
NOTE: The completed guide can be found in the <<httpsession-jdbc-xml-sample, httpsession-jdbc-xml sample application>>.
== 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"]
----
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-version}</version>
</dependency>
</dependencies>
----
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]
----
<repositories>
<!-- ... -->
<repository>
<id>spring-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
----
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]
----
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
----
endif::[]
// tag::config[]
[[httpsession-jdbc-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-jdbc-xml/src/main/webapp/WEB-INF/spring/session.xml[tags=beans]
----
<1> We use the combination of `<context:annotation-config/>` and `JdbcHttpSessionConfiguration` 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 a relational database.
<2> We create a `dataSource` that connects Spring Session to an embedded instance of H2 database.
We configure the H2 database to create database tables using the SQL script which is included in Spring Session.
<3> We create a `transactionManager` that manages transactions for previously configured `dataSource`.
For additional information on how to configure data access related concerns, please refer to the https://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html[Spring Framework Reference Documentation].
== XML Servlet Container Initialization
Our <<httpsession-xml-spring-configuration,Spring Configuration>> 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 https://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 https://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-jdbc-xml-sample]]
== httpsession-jdbc-xml Sample Application
=== Running the httpsession-jdbc-xml Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
----
$ ./gradlew :samples:httpsession-jdbc-xml:tomcatRun
----
You should now be able to access the application at http://localhost:8080/
=== Exploring the httpsession-jdbc-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-jdbc-xml/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in H2 database.
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 H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL)
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.

View File

@@ -1,152 +0,0 @@
= Spring Session - HttpSession (Quick Start)
Rob Winch, Vedran Pavić
:toc:
This guide describes how to use Spring Session to transparently leverage a relational database to back a web application's `HttpSession` with Java Configuration.
NOTE: The completed guide can be found in the <<httpsession-jdbc-sample, httpsession-jdbc sample application>>.
== 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"]
----
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-jdbc</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>{spring-version}</version>
</dependency>
</dependencies>
----
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]
----
<repositories>
<!-- ... -->
<repository>
<id>spring-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
----
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]
----
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
----
endif::[]
// tag::config[]
[[httpsession-jdbc-spring-configuration]]
== Spring Java 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:
[source,java]
----
include::{samples-dir}httpsession-jdbc/src/main/java/sample/Config.java[tags=class]
----
<1> The `@EnableJdbcHttpSession` annotation 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 a relational database.
<2> We create a `dataSource` that connects Spring Session to an embedded instance of H2 database.
We configure the H2 database to create database tables using the SQL script which is included in Spring Session.
<3> We create a `transactionManager` that manages transactions for previously configured `dataSource`.
For additional information on how to configure data access related concerns, please refer to the https://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html[Spring Framework Reference Documentation].
== Java Servlet Container Initialization
Our <<httpsession-spring-configuration,Spring Configuration>> 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, Spring needs to load our `Config` class.
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
Fortunately, Spring Session provides a utility class named `AbstractHttpSessionApplicationInitializer` both of these steps extremely easy.
You can find an example below:
.src/main/java/sample/Initializer.java
[source,java]
----
include::{samples-dir}httpsession/src/main/java/sample/Initializer.java[tags=class]
----
NOTE: The name of our class (Initializer) does not matter. What is important is that we extend `AbstractHttpSessionApplicationInitializer`.
<1> The first step is to extend `AbstractHttpSessionApplicationInitializer`.
This ensures that the Spring Bean by the name `springSessionRepositoryFilter` is registered with our Servlet Container for every request.
<2> `AbstractHttpSessionApplicationInitializer` also provides a mechanism to easily ensure Spring loads our `Config`.
// end::config[]
[[httpsession-jdbc-sample]]
== httpsession-jdbc Sample Application
=== Running the httpsession-jdbc Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
----
$ ./gradlew :samples:httpsession-jdbc:tomcatRun
----
You should now be able to access the application at http://localhost:8080/
=== Exploring the httpsession-jdbc 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-jdbc/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in H2 database.
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 H2 web console available at: http://localhost:8080/h2-console/ (use `jdbc:h2:mem:testdb` for JDBC URL)
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.

View File

@@ -85,7 +85,7 @@ The filter is what is in charge of replacing the `HttpSession` implementation to
In this instance Spring Session is backed by Redis.
<2> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
For more information on configuring Spring Data Redis, refer to the https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation].
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
@@ -103,7 +103,7 @@ include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/web.xml[tags=conte
include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/web.xml[tags=listeners]
----
The https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener] reads the contextConfigLocation and picks up our session.xml configuration.
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:
@@ -114,7 +114,7 @@ The following snippet performs this last step for us:
include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/web.xml[tags=springSessionRepositoryFilter]
----
The https://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`.
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[]
@@ -128,7 +128,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
@@ -165,7 +165,7 @@ If you like, you can easily remove the session using redis-cli. For example, on
$ redis-cli keys '*' | xargs redis-cli del
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
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:

View File

@@ -83,7 +83,7 @@ The filter is what is in charge of replacing the `HttpSession` implementation to
In this instance Spring Session is backed by Redis.
<2> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
For more information on configuring Spring Data Redis, refer to the https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation].
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].
== Java Servlet Container Initialization
@@ -120,7 +120,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
@@ -157,7 +157,7 @@ If you like, you can easily remove the session using redis-cli. For example, on
$ redis-cli keys '*' | xargs redis-cli del
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
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:

View File

@@ -1,169 +0,0 @@
= Spring Session - Mongo Repositories
Jakub Kubrynski
:toc:
This guide describes how to use Spring Session backed by Mongo.
NOTE: The completed guide can be found in the <<mongo-sample, mongo sample application>>.
== Updating Dependencies
Before you use Spring Session, you must ensure to update your dependencies.
We assume you are working with a working Spring Boot web application.
If you are using Maven, ensure to add the following dependencies:
.pom.xml
[source,xml]
[subs="verbatim,attributes"]
----
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-mongo</artifactId>
<version>{spring-session-version}</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
</dependencies>
----
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]
----
<repositories>
<!-- ... -->
<repository>
<id>spring-snapshot</id>
<url>https://repo.spring.io/libs-snapshot</url>
</repository>
</repositories>
----
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]
----
<repository>
<id>spring-milestone</id>
<url>https://repo.spring.io/libs-milestone</url>
</repository>
----
endif::[]
[[mongo-spring-configuration]]
== Spring 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.
// tag::config[]
All you have to do is to add the following Spring Configuration:
[source,java]
----
include::{samples-dir}mongo/src/main/java/sample/config/HttpSessionConfig.java[tags=class]
----
<1> The `@EnableMongoHttpSession` annotation 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 Mongo.
<2> We explicitly configure `JdkMongoSessionConverter` since Spring Security's objects cannot be automatically persisted using Jackson (the default if Jackson is on the classpath).
// end::config[]
[[boot-mongo-configuration]]
== Configuring the Mongo Connection
Spring Boot automatically creates a `MongoClient` that connects Spring Session to a Mongo Server on localhost on port 27017 (default port).
In a production environment you need to ensure to update your configuration to point to your Mongo server.
For example, you can include the following in your *application.properties*
.src/main/resources/application.properties
----
spring.data.mongodb.host=mongo-srv
spring.data.mongodb.port=27018
spring.data.mongodb.database=prod
----
For more information, refer to https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-connecting-to-mongodb[Connecting to MongoDB] portion of the Spring Boot documentation.
[[boot-servlet-configuration]]
== Servlet Container Initialization
Our <<boot-spring-configuration,Spring Configuration>> 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, Spring needs to load our `Config` class.
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
Fortunately, Spring Boot takes care of both of these steps for us.
[[mongo-sample]]
== Mongo Sample Application
The Mongo Sample Application demonstrates how to use Spring Session to transparently leverage Mongo to back a web application's `HttpSession` when using Spring Boot.
[[mongo-running]]
=== Running the Mongo Sample Application
You can run the sample by obtaining the {download-url}[source code] and invoking the following command:
----
$ ./gradlew :samples:mongo:bootRun
----
You should now be able to access the application at http://localhost:8080/
[[boot-explore]]
=== Exploring the security Sample Application
Try using the application. Enter the following to log in:
* **Username** _user_
* **Password** _password_
Now click the **Login** button.
You should now see a message indicating your are logged in with the user entered previously.
The user's information is stored in Mongo rather than Tomcat's `HttpSession` implementation.
[[mongo-how]]
=== How does it work?
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Mongo.
Spring Session replaces the `HttpSession` with an implementation that is backed by Mongo.
When Spring Security's `SecurityContextPersistenceFilter` saves the `SecurityContext` to the `HttpSession` it is then persisted into Mongo.
When a new `HttpSession` is created, 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 inspect the session using mongo client. For example, on a Linux based system you can type:
[NOTE]
====
The sample application uses an embedded MongoDB instance that listens on a randomly allocated port.
The port used by embedded MongoDB together with exact command to connect to it is logged during application startup.
====
$ mongo --port ...
> use test
> db.sessions.find().pretty()
Alternatively, you can also delete the explicit key. Enter the following into your terminal ensuring to replace `60f17293-839b-477c-bb92-07a9c3658843` with the value of your SESSION cookie:
> db.sessions.remove({"_id":"60f17293-839b-477c-bb92-07a9c3658843"})
Now visit the application at http://localhost:8080/ and observe that we are no longer authenticated.

View File

@@ -83,7 +83,7 @@ The filter is what is in charge of replacing the `HttpSession` implementation to
In this instance Spring Session is backed by Redis.
<2> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
For more information on configuring Spring Data Redis, refer to the https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation].
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].
<3> We customize Spring Session's HttpSession integration to use HTTP headers to convey the current session information instead of cookies.
== Servlet Container Initialization
@@ -121,7 +121,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
@@ -160,7 +160,7 @@ Specifically, we notice the following things about our response:
* We have a header with the name of *x-auth-token* which contains a new session id
* The current username is displayed
We can now use the *x-auth-token* to make another request without providing the username and password again. For example, the following outputs the username just as before:
We can now use the *x-auth-token* to make another request without providing the username and password again. For example, the following outputs the the username just as before:
$ curl -v http://localhost:8080/ -H "x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
@@ -203,7 +203,7 @@ Now remove the session using redis-cli. For example, on a Linux based system you
$ redis-cli keys '*' | xargs redis-cli del
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
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:

View File

@@ -82,7 +82,7 @@ The filter is what is in charge of replacing the `HttpSession` implementation to
In this instance Spring Session is backed by Redis.
<2> We create a `RedisConnectionFactory` that connects Spring Session to the Redis Server.
We configure the connection to connect to localhost on the default port (6379)
For more information on configuring Spring Data Redis, refer to the https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/[reference documentation].
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].
== Servlet Container Initialization
@@ -125,7 +125,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
@@ -159,7 +159,7 @@ If you like, you can easily remove the session using redis-cli. For example, on
$ redis-cli keys '*' | xargs redis-cli del
TIP: The Redis documentation has instructions for https://redis.io/topics/quickstart[installing redis-cli].
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:

View File

@@ -19,7 +19,7 @@ You can run the sample by obtaining the {download-url}[source code] and invoking
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====
@@ -140,7 +140,7 @@ For example, if the URL is http://localhost:8080/?_s=1 this alias would be used.
The nice thing about specifying the session alias in the URL is that we can have multiple tabs open with different active sessions.
The bad thing is that we need to include the session alias in every URL of our application.
Fortunately, Spring Session will automatically include the session alias in any URL that passes through https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html#encodeURL(java.lang.String)[HttpServletResponse#encodeURL(java.lang.String)]
Fortunately, Spring Session will automatically include the session alias in any URL that passes through http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html#encodeURL(java.lang.String)[HttpServletResponse#encodeURL(java.lang.String)]
This means that if you are using standard tag libraries the session alias is automatically included in the URL.
For example, if we are currently using the session with the alias of *1*, then the following:

View File

@@ -84,7 +84,7 @@ include::{samples-dir}websocket/src/main/java/sample/config/WebSecurityConfig.ja
[NOTE]
====
For the sample to work, you must https://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
For the sample to work, you must http://redis.io/download[install Redis 2.8+] on localhost and run it with the default port (6379).
Alternatively, you can update the `JedisConnectionFactory` to point to a Redis server.
====

View File

@@ -1,5 +1,5 @@
= Spring Session
Rob Winch, Vedran Pavić, Jakub Kubrynski
Rob Winch
:doctype: book
:indexdoc-tests: {docs-test-dir}docs/IndexDocTests.java
:websocketdoc-test-dir: {docs-test-dir}docs/websocket/
@@ -22,15 +22,24 @@ Additional features include:
* <<websocket,WebSocket>> - provides the ability to keep the `HttpSession` alive when receiving WebSocket messages
== What's New in 1.2
== What's New in 1.1
Below are the highlights of what is new in Spring Session 1.2. You can find a complete list of what's new in https://github.com/spring-projects/spring-session/issues?utf8=%E2%9C%93&q=milestone%3A%221.2.0+RC1%22[1.2.0 RC1] by referring to the changelog.
Below are the highlights of what is new in Spring Session 1.1. You can find a complete list of what's new in https://github.com/spring-projects/spring-session/issues?utf8=%E2%9C%93&q=milestone%3A%221.1.0+M1%22[1.1.0 M1], https://github.com/spring-projects/spring-session/issues?utf8=%E2%9C%93&q=milestone%3A%221.1.0+RC1%22[1.1.0 RC1], and
https://github.com/spring-projects/spring-session/issues?utf8=%E2%9C%93&q=milestone%3A%221.1.0%22[1.1.0]
by referring to the changelog.
* Added <<httpsession-jdbc,JdbcOperationsSessionRepository>> (See https://github.com/spring-projects/spring-session/issues/364[#364]).
* Added <<httpsession-mongo,MongoOperationsSessionRepository>> (See https://github.com/spring-projects/spring-session/pull/371[#371]).
* SessionRepositoryFilter caches null session lookup (See https://github.com/spring-projects/spring-session/issues/423[#423])
* link:guides/grails3.html[Grails 3 Sample & Guide]
* Improved Workspace Setup (See https://github.com/spring-projects/spring-session/pull/417[#417])
* https://github.com/spring-projects/spring-session/issues/148[#148] - Added <<httpsession-gemfire,GemFire Support>>
* https://github.com/spring-projects/spring-session/issues/7[#7] - link:guides/findbyusername.html[Query by Username]
* https://github.com/spring-projects/spring-session/issues/299[#299] - link:guides/custom-cookie.html[Customize Cookie Creation]
* https://github.com/spring-projects/spring-session/issues/4[#4] - Add <<httpsession-httpsessionlistener,HttpSessionListener>> support
* https://github.com/spring-projects/spring-session/issues/283[#283] - Allow override default `RedisSerializer`
* https://github.com/spring-projects/spring-session/issues/277[#277] - Added link:guides/hazelcast-spring.html[@EnableHazelcastHttpSession]
* https://github.com/spring-projects/spring-session/issues/271[#271] - Performance improvements
* https://github.com/spring-projects/spring-session/pull/218[#218] - Allow scoping the session in Redis using <<api-redisoperationssessionrepository-config,redisNamespace>>
* https://github.com/spring-projects/spring-session/issues/273[#273] - Allow writing to Redis immediately (instead of lazily) using <<api-redisoperationssessionrepository-config,redisFlushMode>>
* https://github.com/spring-projects/spring-session/issues/272[#272] - Add `ExpiringSession.setLastAccessedTime(long)`
* https://github.com/spring-projects/spring-session/pull/349[#349] - Added https://gitter.im/spring-projects/spring-session[Gitter Room] for discussing Spring Session
* https://github.com/spring-projects/spring-session/issues/388[#388] - Support Spring Framework WebSockets
[[samples]]
== Samples and Guides (Start Here)
@@ -49,10 +58,6 @@ If you are looking to get started with Spring Session, the best place to start i
| Demonstrates how to use Spring Session to replace the `HttpSession` with a Redis store using XML based configuration.
| link:guides/httpsession-xml.html[HttpSession XML Guide]
| {gh-samples-url}httpsession-gemfire-boot[HttpSession with GemFire using Spring Boot]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a Client/Server topology in a Spring Boot application.
| link:guides/httpsession-gemfire-boot.html[HttpSession GemFire Boot Guide]
| {gh-samples-url}httpsession-gemfire-clientserver[HttpSession with GemFire (Client/Server)]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a Client/Server topology.
| link:guides/httpsession-gemfire-clientserver.html[HttpSession GemFire Client/Server Guide]
@@ -77,10 +82,6 @@ If you are looking to get started with Spring Session, the best place to start i
| Demonstrates how to use Spring Session with Spring Boot.
| link:guides/boot.html[Spring Boot Guide]
| {gh-samples-url}grails3[Grails 3]
| Demonstrates how to use Spring Session with Grails 3.
| link:guides/grails3.html[Grails 3 Guide]
| {gh-samples-url}security[Spring Security]
| Demonstrates how to use Spring Session with an existing Spring Security application.
| link:guides/security.html[Spring Security Guide]
@@ -101,10 +102,6 @@ If you are looking to get started with Spring Session, the best place to start i
| Demonstrates how to use Spring Session with WebSockets.
| link:guides/websocket.html[WebSocket Guide]
| {gh-samples-url}mongo[Mongo]
| Demonstrates how to use Spring Session with Mongo.
| link:guides/mongo.html[Mongo Guide]
[[samples-hazelcast]]
| {gh-samples-url}hazelcast[Hazelcast]
| Demonstrates how to use Spring Session with Hazelcast.
@@ -115,18 +112,6 @@ If you are looking to get started with Spring Session, the best place to start i
| Demonstrates how to use Spring Session and Hazelcast with an existing Spring Security application.
| link:guides/hazelcast-spring.html[Hazelcast Spring Guide]
| {gh-samples-url}httpsession-jdbc[HttpSession JDBC]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store.
| link:guides/httpsession-jdbc.html[HttpSession JDBC Guide]
| {gh-samples-url}httpsession-jdbc-xml[HttpSession JDBC XML]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store using XML based configuration.
| link:guides/httpsession-jdbc-xml.html[HttpSession JDBC XML Guide]
| {gh-samples-url}httpsession-jdbc-boot[HttpSession JDBC Spring Boot]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store when using Spring Boot.
| link:guides/httpsession-jdbc-boot.html[HttpSession JDBC Spring Boot Guide]
|===
[[httpsession]]
@@ -158,7 +143,7 @@ You can choose from enabling this using either:
This section describes how to use Redis to back `HttpSession` using Java based configuration.
NOTE: The <<samples, HttpSession Sample>> provides a working sample on how to integrate Spring Session and `HttpSession` using Java configuration.
NOTE: The <<samples, HttpSession Sample>> 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=+3]
@@ -185,14 +170,14 @@ The two most common topologies to manage Spring Sessions using GemFire include:
* <<httpsession-gemfire-clientserver,Client-Server>>
* <<httpsession-gemfire-p2p,Peer-To-Peer (P2P)>>
Additionally, GemFire supports site-to-site replication using https://gemfire.docs.pivotal.io/docs-gemfire/topologies_and_comm/multi_site_configuration/chapter_overview.html[WAN functionality].
Additionally, GemFire supports site-to-site replication using http://gemfire.docs.pivotal.io/docs-gemfire/topologies_and_comm/multi_site_configuration/chapter_overview.html[WAN functionality].
The ability to configure and use GemFire's WAN support is independent of Spring Session, and is beyond the scope
of this document. More details on GemFire WAN functionality can be found https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/#bootstrap:gateway[here].
of this document. More details on GemFire WAN functionality can be found http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/#bootstrap:gateway[here].
[[httpsession-gemfire-clientserver]]
==== GemFire Client-Server
The https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client-Server]
The http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html[Client-Server]
topology will probably be the more common configuration preference for users when using GemFire as a provider in
Spring Session since a GemFire server will have significantly different and unique JVM heap requirements when compared
to the application. Using a client-server topology enables an application to manage (e.g. replicate) application state
@@ -234,14 +219,14 @@ include::guides/httpsession-gemfire-clientserver-xml.adoc[tags=config,leveloffse
==== GemFire Peer-To-Peer (P2P)
Perhaps less common would be to configure the Spring Session application as a peer member in the GemFire cluster using
the https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/p2p_configuration/chapter_overview.html[Peer-To-Peer (P2P)] topology.
the http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/p2p_configuration/chapter_overview.html[Peer-To-Peer (P2P)] topology.
In this configuration, a Spring Session application would be an actual data node (server) in the GemFire cluster,
and **not** a cache client as before.
One advantage to this approach is the proximity of the application to the application's state (i.e. it's data). However,
there are other effective means of accomplishing similar data dependent computations, such as using GemFire's
https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/function_exec/chapter_overview.html[Function Execution].
Any of GemFire's other https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/product_intro.html[features]
http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/function_exec/chapter_overview.html[Function Execution].
Any of GemFire's other http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/product_intro.html[features]
can be used when GemFire is serving as a provider in Spring Session.
P2P is very useful for both testing purposes as well as smaller, more focused and self-contained applications,
@@ -277,97 +262,6 @@ Guide when integrating with your own application.
include::guides/httpsession-gemfire-p2p-xml.adoc[tags=config,leveloffset=+3]
[[httpsession-jdbc]]
=== HttpSession with JDBC
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:
* <<httpsession-jdbc-jc,Java Based Configuration>>
* <<httpsession-jdbc-xml,XML Based Configuration>>
* <<httpsession-jdbc-boot,Spring Boot Based Configuration>>
[[httpsession-jdbc-jc]]
==== JDBC Java Based Configuration
This section describes how to use a relational database to back `HttpSession` using Java based configuration.
NOTE: The <<samples, HttpSession JDBC Sample>> provides a working sample on how to integrate Spring Session and `HttpSession` using Java configuration.
You can read the basic steps for integration below, but you are encouraged to follow along with the detailed HttpSession JDBC Guide when integrating with your own application.
include::guides/httpsession-jdbc.adoc[tags=config,leveloffset=+3]
[[httpsession-jdbc-xml]]
==== JDBC XML Based Configuration
This section describes how to use a relational database to back `HttpSession` using XML based configuration.
NOTE: The <<samples, HttpSession JDBC XML Sample>> 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 JDBC XML Guide when integrating with your own application.
include::guides/httpsession-jdbc-xml.adoc[tags=config,leveloffset=+3]
[[httpsession-jdbc-boot]]
==== JDBC Spring Boot Based Configuration
This section describes how to use a relational database to back `HttpSession` when using Spring Boot.
NOTE: The <<samples, HttpSession JDBC Spring Boot Sample>> provides a working sample on how to integrate Spring Session and `HttpSession` using Spring Boot.
You can read the basic steps for integration below, but you are encouraged to follow along with the detailed HttpSession JDBC Spring Boot Guide when integrating with your own application.
include::guides/httpsession-jdbc-boot.adoc[tags=config,leveloffset=+3]
[[httpsession-mongo]]
=== HttpSession with Mongo
Using Spring Session with `HttpSession` is enabled by adding a Servlet Filter before anything that uses the `HttpSession`.
This section describes how to use Mongo to back `HttpSession` using Java based configuration.
NOTE: The <<samples, HttpSession Mongo Sample>> provides a working sample on how to integrate Spring Session and `HttpSession` using Java 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/mongo.adoc[tags=config,leveloffset=+3]
==== Session serialization mechanisms
To be able to persist session objects in MongoDB we need to provide the serialization/deserialization mechanism.
Depending on your classpath Spring Session will choose one of two build-in converters:
* `JacksonMongoSessionConverter` when `ObjectMapper` class is available, or
* `JdkMongoSessionConverter` otherwise.
===== JacksonMongoSessionConverter
This mechanism uses Jackson to serialize session objects to/from JSON.
`JacksonMongoSessionConverter` will be the default when Jackson is detected on the classpath and the user has not explicitly registered a `AbstractMongoSessionConverter` Bean.
If you would like to provide custom Jackson modules you can do it by explicitly registering `JacksonMongoSessionConverter`:
[source,java,indent=0]
----
include::{docs-test-dir}docs/http/MongoJacksonSessionConfiguration.java[tags=config]
----
==== JdkMongoSessionConverter
`JdkMongoSessionConverter` uses standard Java serialization to persist session attributes map to MongoDB in a binary form.
However, standard session elements like id, access time, etc are still written as a plain Mongo objects and can be read and queried without additional effort.
`JdkMongoSessionConverter` is used if Jackson is not on the classpath and no explicit `AbstractMongoSessionConverter` Bean has been defined.
You can explicitly register `JdkMongoSessionConverter` by defining it as a Bean.
[source,java,indent=0]
----
include::{docs-test-dir}docs/http/MongoJdkSessionConfiguration.java[tags=config]
----
There is also a constructor taking `Serializer` and `Deserializer` objects, allowing you to pass custom implementations, which is especially important when you want to use non-default classloader.
==== Using custom converters
You can create your own session converter by extending `AbstractMongoSessionConverter` class.
The implementation will be used for serializing, deserializing your objects and for providing queries to access the session.
[[httpsession-how]]
=== How HttpSession Integration Works
@@ -613,7 +507,7 @@ This means if you require cleaning up expired sessions, you are responsible for
[[api-enablehazelcasthttpsession]]
=== EnableHazelcastHttpSession
If you wish to use https://hazelcast.org/[Hazelcast] as your backing source for the `SessionRepository`, then the `@EnableHazelcastHttpSession` annotation
If you wish to use http://hazelcast.org/[Hazelcast] as your backing source for the `SessionRepository`, then the `@EnableHazelcastHttpSession` annotation
can be added to an `@Configuration` class. This extends the functionality provided by the `@EnableSpringHttpSession` annotation but makes the `SessionRepository` for you in Hazelcast.
You must provide a single `HazelcastInstance` bean for the configuration to work.
For example:
@@ -624,7 +518,7 @@ include::{docs-test-dir}docs/http/HazelcastHttpSessionConfig.java[tags=config]
----
This will configure Hazelcast in embedded mode with default configuration.
See the https://docs.hazelcast.org/docs/latest/manual/html-single/index.html#hazelcast-configuration[Hazelcast documentation] for
See the http://docs.hazelcast.org/docs/latest/manual/html-single/index.html#hazelcast-configuration[Hazelcast documentation] for
detailed information on configuration options for Hazelcast.
[[api-enablehazelcasthttpsession-storage]]
@@ -687,7 +581,7 @@ You can customize the serialization by creating a Bean named `springSessionDefau
`RedisOperationsSessionRepository` is subscribed to receive events from redis using a `RedisMessageListenerContainer`.
You can customize the way those events are dispatched, by creating a Bean named `springSessionRedisTaskExecutor` and/or a Bean `springSessionRedisSubscriptionExecutor`.
More details on configuring redis task executors can be found https://docs.spring.io/spring-data-redis/docs/current/reference/html/#redis:pubsub:subscribe:containers[here].
More details on configuring redis task executors can be found http://docs.spring.io/spring-data-redis/docs/current/reference/html/#redis:pubsub:subscribe:containers[here].
[[api-redisoperationssessionrepository-storage]]
==== Storage Details
@@ -766,7 +660,7 @@ The `SessionRepository.getSession(String)` method ensures that no expired sessio
This means there is no need to check the expiration before using a session.
====
Spring Session relies on the delete and expired https://redis.io/topics/notifications[keyspace notifications] from Redis to fire a <<api-redisoperationssessionrepository-sessiondestroyedevent,SessionDeletedEvent>> and <<api-redisoperationssessionrepository-sessiondestroyedevent,SessionExpiredEvent>> respectively.
Spring Session relies on the delete and expired http://redis.io/topics/notifications[keyspace notifications] from Redis to fire a <<api-redisoperationssessionrepository-sessiondestroyedevent,SessionDeletedEvent>> and <<api-redisoperationssessionrepository-sessiondestroyedevent,SessionExpiredEvent>> respectively.
It is the `SessionDeletedEvent` or `SessionExpiredEvent` that ensures resources associated with the Session are cleaned up.
For example, when using Spring Session's WebSocket support the Redis expired or delete event is what triggers any WebSocket connections associated with the session to be closed.
@@ -781,7 +675,7 @@ When a session expires key is deleted or expires, the keyspace notification trig
One problem with relying on Redis expiration exclusively is that Redis makes no guarantee of when the expired event will be fired if they key has not been accessed.
Specifically the background task that Redis uses to clean up expired keys is a low priority task and may not trigger the key expiration.
For additional details see https://redis.io/topics/notifications[Timing of expired events] section in the Redis documentation.
For additional details see http://redis.io/topics/notifications[Timing of expired events] section in the Redis documentation.
To circumvent the fact that expired events are not guaranteed to happen we can ensure that each key is accessed when it is expected to expire.
This means that if the TTL is expired on the key, Redis will remove the key and fire the expired event when we try to access they key.
@@ -816,7 +710,7 @@ This is necessary to ensure resources associated with the `Session` are properly
For example, when integrating with WebSockets the `SessionDestroyedEvent` is in charge of closing any active WebSocket connections.
Firing `SessionDeletedEvent` or `SessionExpiredEvent` is made available through the `SessionMessageListener` which listens to https://redis.io/topics/notifications[Redis Keyspace events].
Firing `SessionDeletedEvent` or `SessionExpiredEvent` is made available through the `SessionMessageListener` which listens to http://redis.io/topics/notifications[Redis Keyspace events].
In order for this to work, Redis Keyspace events for Generic commands and Expired events needs to be enabled.
For example:
@@ -855,7 +749,7 @@ If registered as a MessageListener (default), then `RedisOperationsSessionReposi
[[api-redisoperationssessionrepository-cli]]
==== Viewing the Session in Redis
After https://redis.io/topics/quickstart[installing redis-cli], you can inspect the values in Redis https://redis.io/commands#hash[using the redis-cli].
After http://redis.io/topics/quickstart[installing redis-cli], you can inspect the values in Redis http://redis.io/commands#hash[using the redis-cli].
For example, enter the following into a terminal:
[source,bash]
@@ -960,9 +854,9 @@ Session attribute a value that is not `Comparable` and the Session is saved to G
NOTE: Any Session attribute that is not indexed may store non-`Comparable` values.
To learn more about GemFire's Range-based Indexes, see https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/creating_map_indexes.html[Creating Indexes on Map Fields].
To learn more about GemFire's Range-based Indexes, see http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/creating_map_indexes.html[Creating Indexes on Map Fields].
To learn more about GemFire Indexing in general, see https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/query_index.html[Working with Indexes].
To learn more about GemFire Indexing in general, see http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/query_index.html[Working with Indexes].
[[api-mapsessionrepository]]
@@ -999,72 +893,8 @@ To run it use the following:
./gradlew :samples:hazelcast-spring:tomcatRun
[[api-jdbcoperationssessionrepository]]
=== JdbcOperationsSessionRepository
`JdbcOperationsSessionRepository` is a `SessionRepository` implementation that uses Spring's `JdbcOperations` to store sessions in a relational database.
In a web environment, this is typically used in combination with `SessionRepositoryFilter`.
Please note that this implementation does not support publishing of session events.
[[api-jdbcoperationssessionrepository-new]]
==== Instantiating a JdbcOperationsSessionRepository
A typical example of how to create a new instance can be seen below:
[source,java,indent=0]
----
include::{indexdoc-tests}[tags=new-jdbcoperationssessionrepository]
----
For additional information on how to create and configure `JdbcTemplate` and `PlatformTransactionManager`, refer to the https://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html[Spring Framework Reference Documentation].
[[api-jdbcoperationssessionrepository-config]]
==== EnableJdbcHttpSession
In a web environment, the simplest way to create a new `JdbcOperationsSessionRepository` is to use `@EnableJdbcHttpSession`.
Complete example usage can be found in the <<samples>>
You can use the following attributes to customize the configuration:
* **tableName** - the name of database table used by Spring Session to store sessions
* **maxInactiveIntervalInSeconds** - the amount of time before the session will expire in seconds
===== Custom LobHandler
You can customize the BLOB handling by creating a Bean named `springSessionLobHandler` that implements `LobHandler`.
===== Custom ConversionService
You can customize the default serialization and deserialization of the session by providing a `ConversionService` instance.
When working in a typical Spring environment, the default `ConversionService` Bean (named `conversionService`) will be automatically picked up and used for serialization and deserialization.
However, you can override the default `ConversionService` by providing a Bean named `springSessionConversionService`.
[[api-jdbcoperationssessionrepository-storage]]
==== Storage Details
By default, this implementation uses `SPRING_SESSION` and `SPRING_SESSION_ATTRIBUTES` tables to store sessions.
Note that the table name can be easily customized as already described. In that case the table used to store attributes will be named using the provided table name, suffixed with `_ATTRIBUTES`.
Due to the differences between the various database vendors, especially when it comes to storing binary data, make sure to use SQL script specific to your database.
Scripts for most major database vendors are packaged as `org/springframework/session/jdbc/schema-\*.sql`, where `*` is the target database type.
For example, with PostgreSQL database you would use the following schema script:
[source,sql,indent=0]
----
include::{session-main-resources-dir}org/springframework/session/jdbc/schema-postgresql.sql[]
----
And with MySQL database:
[source,sql,indent=0]
----
include::{session-main-resources-dir}org/springframework/session/jdbc/schema-mysql.sql[]
----
==== Transaction management
All JDBC operations in `JdbcOperationsSessionRepository` are executed in a transactional manner.
Transactions are executed with propagation set to `REQUIRES_NEW` in order to avoid unexpected behavior due to interference with existing transactions (for example, executing `save` operation in a thread that already participates in a read-only transaction).
[[api-mapsessionrepository-hazelcast]]
==== Using Spring Session and Hazlecast
[[community]]
== Spring Session Community
@@ -1075,7 +905,7 @@ Please find additional information below.
[[community-support]]
=== Support
You can get help by asking questions on https://stackoverflow.com/questions/tagged/spring-session[StackOverflow with the tag spring-session].
You can get help by asking questions on http://stackoverflow.com/questions/tagged/spring-session[StackOverflow with the tag spring-session].
Similarly we encourage helping others by answering questions on StackOverflow.
[[community-source]]
@@ -1096,7 +926,7 @@ We appreciate https://help.github.com/articles/using-pull-requests/[Pull Request
[[community-license]]
=== License
Spring Session is Open Source software released under the https://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
Spring Session is Open Source software released under the http://www.apache.org/licenses/LICENSE-2.0.html[Apache 2.0 license].
[[minimum-requirements]]
== Minimum Requirements

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2002-2016 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -16,6 +16,8 @@
package docs;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.io.IOException;
import java.net.Socket;
@@ -25,6 +27,14 @@ import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.session.ExpiringSession;
import org.springframework.session.data.gemfire.GemFireOperationsSessionRepository;
import org.springframework.session.data.gemfire.support.GemFireUtils;
import org.springframework.session.events.AbstractSessionEvent;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheClosedException;
import com.gemstone.gemfire.cache.DataPolicy;
@@ -36,23 +46,12 @@ import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.query.Index;
import com.gemstone.gemfire.cache.server.CacheServer;
import org.junit.Before;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.session.ExpiringSession;
import org.springframework.session.data.gemfire.GemFireOperationsSessionRepository;
import org.springframework.session.data.gemfire.support.GemFireUtils;
import org.springframework.session.events.AbstractSessionEvent;
import static org.assertj.core.api.Assertions.assertThat;
/**
* AbstractGemFireIntegrationTests is an abstract base class encapsulating common
* operations for writing Spring Session GemFire integration tests.
* AbstractGemFireIntegrationTests is an abstract base class encapsulating common operations for writing
* Spring Session GemFire integration tests.
*
* @author John Blum
* @since 1.1.0
* @see org.springframework.session.ExpiringSession
* @see org.springframework.session.events.AbstractSessionEvent
* @see com.gemstone.gemfire.cache.Cache
@@ -62,27 +61,27 @@ import static org.assertj.core.api.Assertions.assertThat;
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.server.CacheServer
* @since 1.1.0
*/
public class AbstractGemFireIntegrationTests {
public static final String GEMFIRE_LOG_LEVEL = System
.getProperty("spring.session.data.gemfire.log-level", "warning");
public static final String GEMFIRE_LOG_LEVEL = System.getProperty(
"spring.session.data.gemfire.log-level", "warning");
protected static final boolean DEFAULT_ENABLE_QUERY_DEBUGGING = false;
protected static final boolean GEMFIRE_QUERY_DEBUG = Boolean
.getBoolean("spring.session.data.gemfire.query.debug");
protected static final boolean GEMFIRE_QUERY_DEBUG = Boolean.getBoolean("spring.session.data.gemfire.query.debug");
protected static final int DEFAULT_GEMFIRE_SERVER_PORT = CacheServer.DEFAULT_PORT;
protected static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(20);
protected static final long DEFAULT_WAIT_INTERVAL = 500L;
protected static final long DEFAULT_WAIT_INTERVAL = 500l;
protected static final File WORKING_DIRECTORY = new File(
System.getProperty("user.dir"));
protected static final File WORKING_DIRECTORY = new File(System.getProperty("user.dir"));
protected static final String DEFAULT_PROCESS_CONTROL_FILENAME = "process.ctl";
protected static final String GEMFIRE_LOG_FILE_NAME = System
.getProperty("spring.session.data.gemfire.log-file", "server.log");
protected static final String GEMFIRE_LOG_FILE_NAME = System.getProperty(
"spring.session.data.gemfire.log-file", "server.log");
@Autowired
protected Cache gemfireCache;
@@ -92,17 +91,15 @@ public class AbstractGemFireIntegrationTests {
@Before
public void setup() {
System.setProperty("gemfire.Query.VERBOSE",
String.valueOf(isQueryDebuggingEnabled()));
System.setProperty("gemfire.Query.VERBOSE", String.valueOf(isQueryDebuggingEnabled()));
}
/* (non-Javadoc) */
protected static File createDirectory(String pathname) {
File directory = new File(WORKING_DIRECTORY, pathname);
assertThat(directory.isDirectory() || directory.mkdirs())
.as(String.format("Failed to create directory (%1$s)", directory))
.isTrue();
assertThat(directory.isDirectory() || directory.mkdirs()).as(
String.format("Failed to create directory (%1$s)", directory)).isTrue();
directory.deleteOnExit();
@@ -110,8 +107,7 @@ public class AbstractGemFireIntegrationTests {
}
/* (non-Javadoc) */
protected static List<String> createJavaProcessCommandLine(Class<?> type,
String... args) {
protected static List<String> createJavaProcessCommandLine(Class<?> type, String... args) {
List<String> commandLine = new ArrayList<String>();
String javaHome = System.getProperty("java.home");
@@ -122,8 +118,7 @@ public class AbstractGemFireIntegrationTests {
commandLine.add("-ea");
commandLine.add(String.format("-Dgemfire.log-file=%1$s", GEMFIRE_LOG_FILE_NAME));
commandLine.add(String.format("-Dgemfire.log-level=%1$s", GEMFIRE_LOG_LEVEL));
commandLine
.add(String.format("-Dgemfire.Query.VERBOSE=%1$s", GEMFIRE_QUERY_DEBUG));
commandLine.add(String.format("-Dgemfire.Query.VERBOSE=%1$s", GEMFIRE_QUERY_DEBUG));
commandLine.addAll(extractJvmArguments(args));
commandLine.add("-classpath");
commandLine.add(System.getProperty("java.class.path"));
@@ -162,10 +157,11 @@ public class AbstractGemFireIntegrationTests {
}
/* (non-Javadoc) */
protected static Process run(Class<?> type, File directory, String... args)
throws IOException {
return new ProcessBuilder().command(createJavaProcessCommandLine(type, args))
.directory(directory).start();
protected static Process run(Class<?> type, File directory, String... args) throws IOException {
return new ProcessBuilder()
.command(createJavaProcessCommandLine(type, args))
.directory(directory)
.start();
}
/* (non-Javadoc) */
@@ -174,10 +170,8 @@ public class AbstractGemFireIntegrationTests {
}
/* (non-Javadoc) */
protected static boolean waitForCacheServerToStart(CacheServer cacheServer,
long duration) {
return waitForCacheServerToStart(cacheServer.getBindAddress(),
cacheServer.getPort(), duration);
protected static boolean waitForCacheServerToStart(CacheServer cacheServer, long duration) {
return waitForCacheServerToStart(cacheServer.getBindAddress(), cacheServer.getPort(), duration);
}
/* (non-Javadoc) */
@@ -186,8 +180,7 @@ public class AbstractGemFireIntegrationTests {
}
/* (non-Javadoc) */
protected static boolean waitForCacheServerToStart(final String host, final int port,
long duration) {
protected static boolean waitForCacheServerToStart(final String host, final int port, long duration) {
return waitOnCondition(new Condition() {
AtomicBoolean connected = new AtomicBoolean(false);
@@ -211,8 +204,7 @@ public class AbstractGemFireIntegrationTests {
}, duration);
}
// NOTE this method would not be necessary except Spring Sessions' build does not fork
// the test JVM
// NOTE this method would not be necessary except Spring Sessions' build does not fork the test JVM
// for every test class.
/* (non-Javadoc) */
protected static boolean waitForClientCacheToClose() {
@@ -247,8 +239,7 @@ public class AbstractGemFireIntegrationTests {
/* (non-Javadoc) */
@SuppressWarnings("all")
protected static boolean waitForProcessToStart(Process process, File directory,
long duration) {
protected static boolean waitForProcessToStart(Process process, File directory, long duration) {
final File processControl = new File(directory, DEFAULT_PROCESS_CONTROL_FILENAME);
waitOnCondition(new Condition() {
@@ -266,8 +257,7 @@ public class AbstractGemFireIntegrationTests {
}
/* (non-Javadoc) */
protected static int waitForProcessToStop(Process process, File directory,
long duration) {
protected static int waitForProcessToStop(Process process, File directory, long duration) {
final long timeout = (System.currentTimeMillis() + duration);
try {
@@ -322,30 +312,24 @@ public class AbstractGemFireIntegrationTests {
}
/* (non-Javadoc) */
protected void assertRegion(Region<?, ?> actualRegion, String expectedName,
DataPolicy expectedDataPolicy) {
protected void assertRegion(Region<?, ?> actualRegion, String expectedName, DataPolicy expectedDataPolicy) {
assertThat(actualRegion).isNotNull();
assertThat(actualRegion.getName()).isEqualTo(expectedName);
assertThat(actualRegion.getFullPath())
.isEqualTo(GemFireUtils.toRegionPath(expectedName));
assertThat(actualRegion.getFullPath()).isEqualTo(GemFireUtils.toRegionPath(expectedName));
assertThat(actualRegion.getAttributes()).isNotNull();
assertThat(actualRegion.getAttributes().getDataPolicy())
.isEqualTo(expectedDataPolicy);
assertThat(actualRegion.getAttributes().getDataPolicy()).isEqualTo(expectedDataPolicy);
}
/* (non-Javadoc) */
protected void assertIndex(Index index, String expectedExpression,
String expectedFromClause) {
protected void assertIndex(Index index, String expectedExpression, String expectedFromClause) {
assertThat(index).isNotNull();
assertThat(index.getIndexedExpression()).isEqualTo(expectedExpression);
assertThat(index.getFromClause()).isEqualTo(expectedFromClause);
}
/* (non-Javadoc) */
protected void assertEntryIdleTimeout(Region<?, ?> region,
ExpirationAction expectedAction, int expectedTimeout) {
assertEntryIdleTimeout(region.getAttributes().getEntryIdleTimeout(),
expectedAction, expectedTimeout);
protected void assertEntryIdleTimeout(Region<?, ?> region, ExpirationAction expectedAction, int expectedTimeout) {
assertEntryIdleTimeout(region.getAttributes().getEntryIdleTimeout(), expectedAction, expectedTimeout);
}
/* (non-Javadoc) */
@@ -372,7 +356,7 @@ public class AbstractGemFireIntegrationTests {
List<String> regionList = new ArrayList<String>(regions.size());
for (Region<?, ?> region : regions) {
for (Region<?,?> region : regions) {
regionList.add(region.getFullPath());
}
@@ -382,7 +366,7 @@ public class AbstractGemFireIntegrationTests {
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
protected <T extends ExpiringSession> T createSession() {
T expiringSession = (T) this.sessionRepository.createSession();
T expiringSession = (T) sessionRepository.createSession();
assertThat(expiringSession).isNotNull();
return expiringSession;
}
@@ -397,19 +381,19 @@ public class AbstractGemFireIntegrationTests {
/* (non-Javadoc) */
protected <T extends ExpiringSession> T expire(T session) {
session.setLastAccessedTime(0L);
session.setLastAccessedTime(0l);
return session;
}
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
protected <T extends ExpiringSession> T get(String sessionId) {
return (T) this.sessionRepository.getSession(sessionId);
return (T) sessionRepository.getSession(sessionId);
}
/* (non-Javadoc) */
protected <T extends ExpiringSession> T save(T session) {
this.sessionRepository.save(session);
sessionRepository.save(session);
return session;
}
@@ -420,14 +404,13 @@ public class AbstractGemFireIntegrationTests {
}
/**
* The SessionEventListener class is a Spring {@link ApplicationListener} listening
* for Spring HTTP Session application events.
* The SessionEventListener class is a Spring {@link ApplicationListener} listening for Spring HTTP Session
* application events.
*
* @see org.springframework.context.ApplicationListener
* @see org.springframework.session.events.AbstractSessionEvent
*/
public static class SessionEventListener
implements ApplicationListener<AbstractSessionEvent> {
public static class SessionEventListener implements ApplicationListener<AbstractSessionEvent> {
private volatile AbstractSessionEvent sessionEvent;
@@ -441,14 +424,14 @@ public class AbstractGemFireIntegrationTests {
/* (non-Javadoc) */
public void onApplicationEvent(AbstractSessionEvent event) {
this.sessionEvent = event;
sessionEvent = event;
}
/* (non-Javadoc) */
public <T extends AbstractSessionEvent> T waitForSessionEvent(long duration) {
waitOnCondition(new Condition() {
public boolean evaluate() {
return (SessionEventListener.this.sessionEvent != null);
return (sessionEvent != null);
}
}, duration);
@@ -457,8 +440,7 @@ public class AbstractGemFireIntegrationTests {
}
/**
* The Condition interface defines a logical condition that must be satisfied before
* it is safe to proceed.
* The Condition interface defines a logical condition that must be satisfied before it is safe to proceed.
*/
protected interface Condition {
boolean evaluate();

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2002-2016 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Map;
import java.util.Properties;
import docs.AbstractGemFireIntegrationTests;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.gemfire.CacheFactoryBean;
@@ -37,7 +36,7 @@ import org.springframework.session.data.gemfire.config.annotation.web.http.Enabl
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.Assertions.assertThat;
import docs.AbstractGemFireIntegrationTests;
/**
* @author Rob Winch
@@ -60,8 +59,7 @@ public class HttpSessionGemFireIndexingITests extends AbstractGemFireIntegration
sessionRepository.save(session);
// tag::findbyindexname-get[]
Map<String, ExpiringSession> idToSessions = sessionRepository
.findByIndexNameAndIndexValue(indexName, username);
Map<String,ExpiringSession> idToSessions = sessionRepository.findByIndexNameAndIndexValue(indexName, username);
// end::findbyindexname-get[]
assertThat(idToSessions.keySet()).containsOnly(session.getId());
@@ -79,15 +77,12 @@ public class HttpSessionGemFireIndexingITests extends AbstractGemFireIntegration
Authentication authentication = context.getAuthentication();
// end::findbyspringsecurityindexname-context[]
session.setAttribute(
HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
context);
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context);
sessionRepository.save(session);
// tag::findbyspringsecurityindexname-get[]
String indexName = FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME;
Map<String, ExpiringSession> idToSessions = sessionRepository
.findByIndexNameAndIndexValue(indexName, authentication.getName());
Map<String,ExpiringSession> idToSessions = sessionRepository.findByIndexNameAndIndexValue(indexName, authentication.getName());
// end::findbyspringsecurityindexname-get[]
assertThat(idToSessions.keySet()).containsOnly(session.getId());
@@ -115,7 +110,9 @@ public class HttpSessionGemFireIndexingITests extends AbstractGemFireIntegration
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setLazyInitialize(false);
gemfireCache.setProperties(gemfireProperties());
gemfireCache.setUseBeanFactoryLocator(false);
return gemfireCache;
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2002-2016 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,17 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http.gemfire.indexablesessionattributes;
import java.util.Properties;
import docs.AbstractGemFireIntegrationTests;
import org.springframework.context.annotation.Bean;
import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
import docs.AbstractGemFireIntegrationTests;
/**
* @author Rob Winch
*
@@ -31,7 +30,7 @@ import org.springframework.session.data.gemfire.config.annotation.web.http.Enabl
// tag::class-start[]
@EnableGemFireHttpSession(indexableSessionAttributes = { "name1", "name2", "name3" })
public class GemFireHttpSessionConfig {
// end::class-start[]
// end::class-start[]
@Bean
Properties gemfireProperties() {
@@ -39,8 +38,7 @@ public class GemFireHttpSessionConfig {
gemfireProperties.setProperty("name", GemFireHttpSessionConfig.class.getName());
gemfireProperties.setProperty("mcast-port", "0");
gemfireProperties.setProperty("log-level",
AbstractGemFireIntegrationTests.GEMFIRE_LOG_LEVEL);
gemfireProperties.setProperty("log-level", AbstractGemFireIntegrationTests.GEMFIRE_LOG_LEVEL);
return gemfireProperties;
}
@@ -50,7 +48,9 @@ public class GemFireHttpSessionConfig {
CacheFactoryBean gemfireCache = new CacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setLazyInitialize(false);
gemfireCache.setProperties(gemfireProperties());
gemfireCache.setUseBeanFactoryLocator(false);
return gemfireCache;
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2002-2016 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,29 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http.gemfire.indexablesessionattributes;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.Map;
import docs.AbstractGemFireIntegrationTests;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.session.ExpiringSession;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static org.assertj.core.api.Assertions.assertThat;
import docs.AbstractGemFireIntegrationTests;
/**
* @author Rob Winch
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = GemFireHttpSessionConfig.class)
public class HttpSessionGemFireIndexingCustomITests
extends AbstractGemFireIntegrationTests {
@ContextConfiguration(classes=GemFireHttpSessionConfig.class)
public class HttpSessionGemFireIndexingCustomITests extends AbstractGemFireIntegrationTests {
@Test
public void findByIndexName() {
@@ -50,8 +48,7 @@ public class HttpSessionGemFireIndexingCustomITests
sessionRepository.save(session);
// tag::findbyindexname-get[]
Map<String, ExpiringSession> idToSessions = sessionRepository
.findByIndexNameAndIndexValue(indexName, attrValue);
Map<String,ExpiringSession> idToSessions = sessionRepository.findByIndexNameAndIndexValue(indexName, attrValue);
// end::findbyindexname-get[]
assertThat(idToSessions.keySet()).containsOnly(session.getId());

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2002-2016 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs;
import java.util.Map;
@@ -22,7 +21,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
@@ -41,8 +39,7 @@ public class FindByIndexNameSessionRepositoryTests {
public void setUsername() {
// tag::set-username[]
String username = "username";
this.session.setAttribute(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
session.setAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
// end::set-username[]
}
@@ -51,10 +48,8 @@ public class FindByIndexNameSessionRepositoryTests {
public void findByUsername() {
// tag::findby-username[]
String username = "username";
Map<String, Session> sessionIdToSession = this.sessionRepository
.findByIndexNameAndIndexValue(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
username);
Map<String,Session> sessionIdToSession =
sessionRepository.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME, username);
// end::findby-username[]
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.mock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.session.ExpiringSession;
@@ -27,9 +28,6 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* @author Rob Winch
*/
@@ -42,9 +40,10 @@ public class HttpSessionConfigurationNoOpConfigureRedisActionXmlTests {
@Test
public void redisConnectionFactoryNotUsedSinceNoValidation() {
assertThat(this.filter).isNotNull();
assertThat(filter).isNotNull();
}
static RedisConnectionFactory connectionFactory() {
return mock(RedisConnectionFactory.class);
}

View File

@@ -1,49 +1,42 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.
* 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.junit.Test;
import static org.assertj.core.api.Assertions.*;
import org.junit.Test;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
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.jdbc.JdbcOperationsSessionRepository;
import org.springframework.session.web.http.SessionRepositoryFilter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Rob Winch
* @author Vedran Pavic
*/
public class IndexDocTests {
static final String ATTR_USER = "user";
@Test
public void repositoryDemo() {
RepositoryDemo<ExpiringSession> demo = new RepositoryDemo<ExpiringSession>();
ExpiringRepositoryDemo<ExpiringSession> demo = new ExpiringRepositoryDemo<ExpiringSession>();
demo.repository = new MapSessionRepository();
demo.demo();
@@ -54,15 +47,15 @@ public class IndexDocTests {
private SessionRepository<S> repository; // <1>
public void demo() {
S toSave = this.repository.createSession(); // <2>
S toSave = repository.createSession(); // <2>
// <3>
User rwinch = new User("rwinch");
toSave.setAttribute(ATTR_USER, rwinch);
this.repository.save(toSave); // <4>
repository.save(toSave); // <4>
S session = this.repository.getSession(toSave.getId()); // <5>
S session = repository.getSession(toSave.getId()); // <5>
// <6>
User user = session.getAttribute(ATTR_USER);
@@ -73,6 +66,7 @@ public class IndexDocTests {
}
// end::repository-demo[]
@Test
public void expireRepositoryDemo() {
ExpiringRepositoryDemo<ExpiringSession> demo = new ExpiringRepositoryDemo<ExpiringSession>();
@@ -81,18 +75,19 @@ public class IndexDocTests {
demo.demo();
}
@SuppressWarnings("unused")
// tag::expire-repository-demo[]
public class ExpiringRepositoryDemo<S extends ExpiringSession> {
private SessionRepository<S> repository; // <1>
public void demo() {
S toSave = this.repository.createSession(); // <2>
S toSave = repository.createSession(); // <2>
// ...
toSave.setMaxInactiveIntervalInSeconds(30); // <3>
this.repository.save(toSave); // <4>
repository.save(toSave); // <4>
S session = this.repository.getSession(toSave.getId()); // <5>
S session = repository.getSession(toSave.getId()); // <5>
// ...
}
@@ -105,8 +100,8 @@ public class IndexDocTests {
public void newRedisOperationsSessionRepository() {
// tag::new-redisoperationssessionrepository[]
JedisConnectionFactory factory = new JedisConnectionFactory();
SessionRepository<? extends ExpiringSession> repository = new RedisOperationsSessionRepository(
factory);
SessionRepository<? extends ExpiringSession> repository =
new RedisOperationsSessionRepository(factory);
// end::new-redisoperationssessionrepository[]
}
@@ -118,23 +113,6 @@ public class IndexDocTests {
// end::new-mapsessionrepository[]
}
@Test
@SuppressWarnings("unused")
public void newJdbcOperationsSessionRepository() {
// tag::new-jdbcoperationssessionrepository[]
JdbcTemplate jdbcTemplate = new JdbcTemplate();
// ... configure JdbcTemplate ...
PlatformTransactionManager transactionManager = new DataSourceTransactionManager();
// ... configure transactionManager ...
SessionRepository<? extends ExpiringSession> repository =
new JdbcOperationsSessionRepository(jdbcTemplate, transactionManager);
// end::new-jdbcoperationssessionrepository[]
}
@Test
public void runSpringHttpSessionConfig() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
@@ -144,14 +122,12 @@ public class IndexDocTests {
try {
context.getBean(SessionRepositoryFilter.class);
}
finally {
} finally {
context.close();
}
}
private static final class User {
private User(String username) {
}
private static class User {
private User(String username) {}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,12 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs;
import static org.mockito.Mockito.mock;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
@@ -28,8 +28,6 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import static org.mockito.Mockito.mock;
/**
* @author Rob Winch
*/
@@ -39,8 +37,7 @@ import static org.mockito.Mockito.mock;
public class RedisHttpSessionConfigurationNoOpConfigureRedisActionTests {
@Test
public void redisConnectionFactoryNotUsedSinceNoValidation() {
}
public void redisConnectionFactoryNotUsedSinceNoValidation() {}
@EnableRedisHttpSession
@Configuration

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs;
import org.springframework.context.annotation.Bean;
@@ -30,4 +29,4 @@ public class SpringHttpSessionConfig {
return new MapSessionRepository();
}
}
// end::class[]
// end::class[]

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,12 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationListener;
@@ -30,10 +32,6 @@ import org.springframework.session.Session;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* @author Rob Winch
* @since 1.2
@@ -51,38 +49,32 @@ public abstract class AbstractHttpSessionListenerTests {
public void springSessionDestroyedTranslatedToSpringSecurityDestroyed() {
Session session = new MapSession();
this.publisher.publishEvent(
new org.springframework.session.events.SessionDestroyedEvent(this,
session));
publisher.publishEvent(new org.springframework.session.events.SessionDestroyedEvent(this, session));
assertThat(this.listener.getEvent().getId()).isEqualTo(session.getId());
assertThat(listener.getEvent().getId()).isEqualTo(session.getId());
}
static RedisConnectionFactory createMockRedisConnection() {
RedisConnectionFactory factory = mock(RedisConnectionFactory.class);
RedisConnection connection = mock(RedisConnection.class);
given(factory.getConnection()).willReturn(connection);
when(factory.getConnection()).thenReturn(connection);
return factory;
}
static class SecuritySessionDestroyedListener
implements ApplicationListener<SessionDestroyedEvent> {
static class SecuritySessionDestroyedListener implements ApplicationListener<SessionDestroyedEvent> {
private SessionDestroyedEvent event;
/*
* (non-Javadoc)
*
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.
* springframework.context.ApplicationEvent)
/* (non-Javadoc)
* @see org.springframework.context.ApplicationListener#onApplicationEvent(org.springframework.context.ApplicationEvent)
*/
public void onApplicationEvent(SessionDestroyedEvent event) {
this.event = event;
}
public SessionDestroyedEvent getEvent() {
return this.event;
return event;
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,17 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.hazelcast.config.annotation.web.http.EnableHazelcastHttpSession;
import com.hazelcast.config.Config;
import com.hazelcast.core.Hazelcast;
import com.hazelcast.core.HazelcastInstance;
//tag::config[]
@EnableHazelcastHttpSession // <1>
@Configuration
@@ -34,4 +33,4 @@ public class HazelcastHttpSessionConfig {
return Hazelcast.newHazelcastInstance(hazelcastConfig); // <2>
}
}
// end::config[]
// end::config[]

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http;
import org.springframework.context.annotation.Bean;

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http;
import org.springframework.test.context.ContextConfiguration;

View File

@@ -1,48 +0,0 @@
/*
* Copyright 2014-2016 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
*
* https://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.http;
import java.util.Collections;
import com.fasterxml.jackson.databind.Module;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.data.mongo.AbstractMongoSessionConverter;
import org.springframework.session.data.mongo.JacksonMongoSessionConverter;
import org.springframework.session.data.mongo.config.annotation.web.http.EnableMongoHttpSession;
/**
*
* @author Jakub Kubrynski
* @author Rob Winch
*/
// tag::config[]
@Configuration
@EnableMongoHttpSession
public class MongoJacksonSessionConfiguration {
@Bean
public AbstractMongoSessionConverter mongoSessionConverter() {
return new JacksonMongoSessionConverter(getJacksonModules());
}
public Iterable<Module> getJacksonModules() {
return Collections.<Module>singletonList(new MyJacksonModule());
}
}
// end::config[]

View File

@@ -1,22 +0,0 @@
/*
* Copyright 2014-2016 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
*
* https://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.http;
import com.fasterxml.jackson.databind.module.SimpleModule;
class MyJacksonModule extends SimpleModule {
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package docs.http;
import org.springframework.context.annotation.Bean;
@@ -33,4 +32,4 @@ public class RedisHttpSessionConfig {
// ...
}
// end::config[]
// end::config[]

View File

@@ -1,19 +1,18 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.
* 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.websocket;
import org.springframework.context.annotation.Configuration;
@@ -24,16 +23,18 @@ import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBr
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
/**
* @author Rob Winch
*/
* @author Rob Winch
*/
// tag::class[]
@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
public class WebSocketConfig
extends AbstractWebSocketMessageBrokerConfigurer {
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/messages").withSockJS();
registry.addEndpoint("/messages")
.withSockJS();
}
@Override
@@ -42,4 +43,4 @@ public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
registry.setApplicationDestinationPrefixes("/app");
}
}
// end::class[]
// end::class[]

View File

@@ -4,9 +4,9 @@
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util-4.1.xsd">
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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<context:annotation-config/>
@@ -19,4 +19,4 @@
<bean class="docs.HttpSessionConfigurationNoOpConfigureRedisActionXmlTests"
factory-method="connectionFactory"/>
</beans>
</beans>

View File

@@ -4,9 +4,9 @@
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util-4.1.xsd">
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
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<!-- tag::config[] -->
<bean class="org.springframework.security.web.session.HttpSessionEventPublisher"/>
@@ -19,4 +19,4 @@
<bean class="docs.http.AbstractHttpSessionListenerTests"
factory-method="createMockRedisConnection"/>
<bean class="docs.http.AbstractHttpSessionListenerTests$SecuritySessionDestroyedListener"/>
</beans>
</beans>

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
<local-check-config name="Spring Session Checkstyle" location="${configDir}/checkstyle.xml" type="external" description="">
<property name="configDir" value="${configDir}"/>
<additional-data name="protect-config-file" value="false"/>
</local-check-config>
<fileset name="all" enabled="true" check-config-name="Spring Session Checkstyle" local="true">
<file-match-pattern match-pattern="." include-pattern="true"/>
</fileset>
</fileset-config>

View File

@@ -1,391 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.codeComplete.argumentPrefixes=
org.eclipse.jdt.core.codeComplete.argumentSuffixes=
org.eclipse.jdt.core.codeComplete.fieldPrefixes=
org.eclipse.jdt.core.codeComplete.fieldSuffixes=
org.eclipse.jdt.core.codeComplete.localPrefixes=
org.eclipse.jdt.core.codeComplete.localSuffixes=
org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
org.eclipse.jdt.core.codeComplete.staticFinalFieldPrefixes=
org.eclipse.jdt.core.codeComplete.staticFinalFieldSuffixes=
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.6
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.doc.comment.support=enabled
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=default
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public
org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=all_standard_tags
org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsMethodTypeParameters=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=default
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nullReference=ignore
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.compiler.processAnnotations=disabled
org.eclipse.jdt.core.compiler.source=1.6
org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
org.eclipse.jdt.core.formatter.alignment_for_assignment=0
org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0
org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80
org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16
org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
org.eclipse.jdt.core.formatter.blank_lines_after_package=1
org.eclipse.jdt.core.formatter.blank_lines_before_field=0
org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
org.eclipse.jdt.core.formatter.blank_lines_before_method=1
org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
org.eclipse.jdt.core.formatter.blank_lines_before_package=0
org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
org.eclipse.jdt.core.formatter.comment.format_block_comments=true
org.eclipse.jdt.core.formatter.comment.format_header=false
org.eclipse.jdt.core.formatter.comment.format_html=true
org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
org.eclipse.jdt.core.formatter.comment.format_line_comments=true
org.eclipse.jdt.core.formatter.comment.format_source_code=false
org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
org.eclipse.jdt.core.formatter.comment.indent_root_tags=false
org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=do not insert
org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert
org.eclipse.jdt.core.formatter.comment.line_length=90
org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true
org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true
org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false
org.eclipse.jdt.core.formatter.compact_else_if=true
org.eclipse.jdt.core.formatter.continuation_indentation=2
org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off
org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on
org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_empty_lines=false
org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
org.eclipse.jdt.core.formatter.indentation.size=4
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert
org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
org.eclipse.jdt.core.formatter.join_lines_in_comments=true
org.eclipse.jdt.core.formatter.join_wrapped_lines=true
org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
org.eclipse.jdt.core.formatter.lineSplit=90
org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
org.eclipse.jdt.core.formatter.tabulation.char=tab
org.eclipse.jdt.core.formatter.tabulation.size=4
org.eclipse.jdt.core.formatter.use_on_off_tags=true
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true
org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true
org.eclipse.jdt.core.javaFormatter=org.springframework.ide.eclipse.jdt.formatter.javaformatter

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="12">
<profile kind="CodeFormatterProfile" name="Spring Session Java Conventions" version="12">
<profile kind="CodeFormatterProfile" name="Spring" version="12">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
@@ -13,7 +13,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
@@ -31,9 +31,9 @@
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
@@ -65,7 +65,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="90"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
@@ -79,7 +79,7 @@
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
@@ -133,7 +133,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
@@ -161,7 +161,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
@@ -175,9 +175,9 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
@@ -202,7 +202,7 @@
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
@@ -266,7 +266,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
@@ -283,7 +283,7 @@
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>

View File

@@ -1,13 +1,10 @@
bootstrapVersion=2.3.2
commonsPoolVersion=2.4.2
jacksonVersion=2.6.5
jspApiVersion=2.0
servletApiVersion=3.0.1
jstlelVersion=1.2.5
version=1.2.3.BUILD-SNAPSHOT
springDataRedisVersion=1.7.1.RELEASE
html5ShivVersion=3.7.3
commonsLoggingVersion=1.2
version=1.1.1.RELEASE
springDataRedisVersion=1.6.2.RELEASE
junitVersion=4.12
gebVersion=0.13.1
mockitoVersion=1.10.19
@@ -16,11 +13,9 @@ seleniumVersion=2.52.0
springSecurityVersion=4.0.3.RELEASE
springVersion=4.2.5.RELEASE
httpClientVersion=4.5.1
jedisVersion=2.8.1
h2Version=1.4.191
springDataMongoVersion=1.9.1.RELEASE
jedisVersion=2.7.3
springShellVersion=1.1.0.RELEASE
springDataGemFireVersion=1.8.1.RELEASE
springDataGemFireVersion=1.7.2.RELEASE
assertjVersion=2.3.0
spockVersion=1.0-groovy-2.4
jstlVersion=1.2.1

View File

@@ -1,50 +0,0 @@
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
import org.gradle.plugins.ide.eclipse.model.SourceFolder
apply plugin: "propdeps-eclipse"
apply plugin: "propdeps-idea"
eclipse.project.buildCommand "net.sf.eclipsecs.core.CheckstyleBuilder"
eclipse.project.natures "net.sf.eclipsecs.core.CheckstyleNature"
// Include project specific settings
task eclipseCheckstyle(type: Copy) {
from rootProject.files(
"eclipse/.checkstyle")
into project.projectDir
expand(configDir: rootProject.file('config/checkstyle').absolutePath)
}
task eclipseSettings(type: Copy) {
from rootProject.files(
"eclipse/org.eclipse.jdt.ui.prefs",
"eclipse/org.eclipse.wst.common.project.facet.core.xml")
into project.file('.settings/')
outputs.upToDateWhen { false }
}
task eclipseWstComponent(type: Copy) {
from rootProject.files(
"eclipse/org.eclipse.wst.common.component")
into project.file('.settings/')
expand(deployname: project.name)
outputs.upToDateWhen { false }
}
task eclipseJdtPrepare(type: Copy) {
from rootProject.file("eclipse/org.eclipse.jdt.core.prefs")
into project.file(".settings/")
outputs.upToDateWhen { false }
}
task cleanEclipseJdtUi(type: Delete) {
delete project.file(".settings/org.eclipse.jdt.core.prefs")
delete project.file(".settings/org.eclipse.jdt.ui.prefs")
delete project.file(".settings/org.eclipse.wst.common.component")
delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml")
}
tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
tasks["eclipse"].dependsOn(eclipseCheckstyle, eclipseSettings, eclipseWstComponent)

View File

@@ -6,8 +6,6 @@ apply plugin: 'propdeps'
apply plugin: 'propdeps-idea'
apply plugin: 'propdeps-eclipse'
apply plugin: 'com.github.ben-manes.versions'
apply plugin: 'checkstyle'
apply from: IDE_GRADLE
group = 'org.springframework.session'
@@ -77,16 +75,6 @@ task integrationTest(type: Test, dependsOn: jar) {
}
check.dependsOn integrationTest
checkstyle {
configFile = rootProject.file('config/checkstyle/checkstyle.xml')
configProperties.configDir = configFile.parentFile
toolVersion = '6.16.1'
}
task checkstyle {
dependsOn project.tasks.findAll { task -> task.name.matches('checkstyle\\w+') }
}
eclipse {
classpath {
plusConfigurations += [ configurations.integrationTestCompile ]
@@ -95,4 +83,4 @@ eclipse {
project.idea.module {
scopes.TEST.plus += [project.configurations.integrationTestRuntime]
}
}

View File

@@ -21,12 +21,12 @@ def customizePom(pom, gradleProject) {
url = "https://github.com/spring-projects/spring-session"
organization {
name = "Spring IO"
url = "https://projects.spring.io/spring-session"
url = "http://projects.spring.io/spring-session"
}
licenses {
license {
name "The Apache Software License, Version 2.0"
url "https://www.apache.org/licenses/LICENSE-2.0.txt"
url "http://www.apache.org/licenses/LICENSE-2.0.txt"
distribution "repo"
}
}

View File

@@ -1,4 +0,0 @@
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarqube {
skipProject = true
}

View File

@@ -10,7 +10,8 @@ buildscript {
apply plugin: 'spring-boot'
apply from: JAVA_GRADLE
apply from: SAMPLE_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
group = 'samples'
@@ -20,9 +21,6 @@ dependencies {
"org.springframework.boot:spring-boot-starter-web",
"org.springframework.boot:spring-boot-starter-thymeleaf",
"nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect",
"org.thymeleaf.extras:thymeleaf-extras-conditionalcomments",
"org.webjars:bootstrap:$bootstrapVersion",
"org.webjars:html5shiv:$html5ShivVersion",
"org.springframework.security:spring-security-web:$springSecurityVersion",
"org.springframework.security:spring-security-config:$springSecurityVersion"
@@ -52,4 +50,4 @@ def reservePort() {
def result = socket.localPort
socket.close()
result
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample
import geb.spock.*
@@ -72,4 +71,4 @@ class BootTests extends GebReportingSpec {
then: 'sent to the log in page'
at LoginPage
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.pages
import geb.*

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.pages
import geb.*

View File

@@ -1,28 +1,31 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.
* 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 sample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* @author Rob Winch
*/
@SpringBootApplication
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class Application {
public static void main(String[] args) {

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.config;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
// tag::class[]
@EnableRedisHttpSession // <1>
public class HttpSessionConfig {
}
// end::class[]
public class HttpSessionConfig { }
// end::class[]

View File

@@ -1,19 +1,18 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.
* 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 sample.config;
import org.springframework.beans.factory.annotation.Autowired;
@@ -29,6 +28,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}

View File

@@ -1,19 +1,18 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.
* 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 sample.mvc;
import org.springframework.stereotype.Controller;

View File

@@ -1,2 +1,2 @@
spring.thymeleaf.cache=false
spring.template.cache=false
spring.template.cache=false

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
<html xmlns:th="https://www.thymeleaf.org" xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect" layout:decorator="layout">
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout">
<head>
<title>Secured Content</title>
</head>
@@ -8,4 +8,4 @@
<p>This page is secured using Spring Boot, Spring Session, and Spring Security.</p>
</div>
</body>
</html>
</html>

View File

@@ -1,11 +1,11 @@
<!DOCTYPE html SYSTEM "https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="https://www.thymeleaf.org"
xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect">
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">Spring Session Sample</title>
<link rel="icon" type="image/x-icon" th:href="@{/resources/img/favicon.ico}" href="../static/img/favicon.ico"/>
<link th:href="@{/webjars/bootstrap/2.3.2/css/bootstrap.min.css}" href="/webjars/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet"></link>
<link th:href="@{/resources/css/bootstrap.css}" href="../static/css/bootstrap.css" rel="stylesheet"></link>
<style type="text/css">
/* Sticky footer styles
-------------------------------------------------- */
@@ -65,11 +65,11 @@
margin-left: 1em;
}
</style>
<link th:href="@{/webjars/bootstrap/2.3.2/css/bootstrap-responsive.min.css}" href="/webjars/bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet"></link>
<link th:href="@{resources/css/bootstrap-responsive.css}" href="/static/css/bootstrap-responsive.css" rel="stylesheet"></link>
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script th:src="@{/webjars/html5shiv/3.7.3/html5shiv.min.js}" src="/webjars/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
@@ -82,7 +82,7 @@
<a class="brand" th:href="@{/}"><img th:src="@{/resources/img/logo.png}" alt="Spring Security Sample"/></a>
<div class="nav-collapse collapse"
th:with="currentUser=${#httpServletRequest.userPrincipal?.principal}">
th:with="currentUser=${#httpServletRequest.userPrincipal?.principal}">
<div th:if="${currentUser != null}">
<form class="navbar-form pull-right" th:action="@{/logout}" method="post">
<input type="submit" value="Log out" />
@@ -115,8 +115,8 @@
<div id="footer">
<div class="container">
<p class="muted credit">Visit the <a href="https://spring.io/spring-security">Spring Security</a> site for more <a href="https://github.com/spring-projects/spring-security/blob/master/samples/">samples</a>.</p>
<p class="muted credit">Visit the <a href="http://spring.io/spring-security">Spring Security</a> site for more <a href="https://github.com/spring-projects/spring-security/blob/master/samples/">samples</a>.</p>
</div>
</div>
</body>
</html>
</html>

View File

@@ -1,11 +1,14 @@
apply from: JAVA_GRADLE
apply from: TOMCAT_7_GRADLE
apply from: SAMPLE_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarRunner {
skipProject = true
}
dependencies {
compile project(':spring-session-data-redis'),
"org.springframework:spring-web:$springVersion",
"org.webjars:bootstrap:$bootstrapVersion",
jstlDependencies
providedCompile "javax.servlet:javax.servlet-api:$servletApiVersion"
@@ -13,4 +16,4 @@ dependencies {
testCompile "junit:junit:$junitVersion"
integrationTestCompile gebDependencies
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample
import geb.spock.*
@@ -43,4 +42,4 @@ class AttributeTests extends GebReportingSpec {
attributes[0].name == 'a'
attributes[0].value == 'b'
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.pages
import geb.*

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample;
import org.springframework.context.annotation.Bean;
@@ -22,6 +21,7 @@ import org.springframework.session.data.redis.config.annotation.web.http.EnableR
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.DefaultCookieSerializer;
@EnableRedisHttpSession
public class Config {
@@ -40,4 +40,4 @@ public class Config {
return serializer;
}
// end::cookie-serializer[]
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,16 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample;
import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer;
// tag::class[]
public class Initializer extends AbstractHttpSessionApplicationInitializer { // <1>
public class Initializer
extends AbstractHttpSessionApplicationInitializer { // <1>
public Initializer() {
super(Config.class); // <2>
}
}
// end::class[]
// end::class[]

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,24 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// tag::class[]
@WebServlet("/session")
public class SessionServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String attributeName = req.getParameter("attributeName");
String attributeValue = req.getParameter("attributeValue");
req.getSession().setAttribute(attributeName, attributeValue);
@@ -39,4 +34,4 @@ public class SessionServlet extends HttpServlet {
private static final long serialVersionUID = 2878267318695777395L;
}
// tag::end[]
// tag::end[]

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,7 @@
<html lang="en">
<head>
<title>Session Attributes</title>
<link rel="stylesheet" href="<c:url value="/webjars/bootstrap/2.3.2/css/bootstrap.min.css"/>">
<link rel="stylesheet" href="assets/bootstrap.min.css">
<style type="text/css">
body {
padding: 1em;

View File

@@ -1,4 +1,4 @@
Demonstrates using Spring Session to lookup a user's session by the username.
The sample provides a hook to add the current username to the session (required for finding the user) by providing a custom implementation of Spring Security's `AuthenticationSuccessHandler`.
NOTE: This product includes GeoLite2 data created by MaxMind, available from https://www.maxmind.com
NOTE: This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com

View File

@@ -10,7 +10,8 @@ buildscript {
apply plugin: 'spring-boot'
apply from: JAVA_GRADLE
apply from: SAMPLE_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
group = 'samples'
@@ -20,9 +21,6 @@ dependencies {
"org.springframework.boot:spring-boot-starter-web",
"org.springframework.boot:spring-boot-starter-thymeleaf",
"nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect",
"org.thymeleaf.extras:thymeleaf-extras-conditionalcomments",
"org.webjars:bootstrap:$bootstrapVersion",
"org.webjars:html5shiv:$html5ShivVersion",
"org.springframework.security:spring-security-web:$springSecurityVersion",
"org.springframework.security:spring-security-config:$springSecurityVersion",
"com.maxmind.geoip2:geoip2:2.3.1",
@@ -55,4 +53,4 @@ def reservePort() {
def result = socket.localPort
socket.close()
result
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample
import geb.Browser
@@ -102,4 +101,4 @@ class FindByUsernameTests extends MultiBrowserGebSpec {
then: 'browser a sent to log in'
a.at LoginPage
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample;
import geb.*
import spock.lang.*
@@ -98,4 +97,4 @@ abstract class MultiBrowserGebSpec extends Specification {
def cleanupSpec() {
if (isSpecStepwise()) resetBrowsers()
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.pages
import geb.*

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.pages
import geb.*

View File

@@ -1,19 +1,18 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.
* 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 sample;
import org.springframework.boot.SpringApplication;

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,17 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.config;
import java.io.InputStream;
import com.maxmind.geoip2.DatabaseReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.maxmind.geoip2.DatabaseReader;
/**
*
* @author Rob Winch
@@ -33,9 +32,7 @@ import org.springframework.context.annotation.Configuration;
public class GeoConfig {
@Bean
public DatabaseReader geoDatabaseReader(
@Value("classpath:GeoLite2-City.mmdb") InputStream geoInputStream)
throws Exception {
public DatabaseReader geoDatabaseReader(@Value("classpath:GeoLite2-City.mmdb") InputStream geoInputStream) throws Exception {
return new DatabaseReader.Builder(geoInputStream).build();
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.config;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
@@ -25,6 +24,5 @@ import org.springframework.session.data.redis.config.annotation.web.http.EnableR
*/
// tag::class[]
@EnableRedisHttpSession // <1>
public class HttpSessionConfig {
}
// end::class[]
public class HttpSessionConfig { }
// end::class[]

View File

@@ -1,19 +1,18 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.
* 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 sample.config;
import org.springframework.beans.factory.annotation.Autowired;
@@ -31,14 +30,24 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
// tag::config[]
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/login").permitAll().and().authorizeRequests()
.antMatchers("/resources/**", "/webjars/**").permitAll().anyRequest().authenticated()
.and().logout().permitAll();
http
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.anyRequest().authenticated()
.and()
.logout()
.permitAll();
}
// end::config[]
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user").password("password").roles("USER");
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}

View File

@@ -1,19 +1,18 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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.
* 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 sample.mvc;
import java.security.Principal;
@@ -43,26 +42,22 @@ public class IndexController {
@RequestMapping("/")
public String index(Principal principal, Model model) {
Collection<? extends ExpiringSession> usersSessions = this.sessions
.findByIndexNameAndIndexValue(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
principal.getName())
.values();
Collection<? extends ExpiringSession> usersSessions =
sessions.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
principal.getName()).values();
model.addAttribute("sessions", usersSessions);
return "index";
}
// end::findbyusername[]
@RequestMapping(value = "/sessions/{sessionIdToDelete}", method = RequestMethod.DELETE)
public String removeSession(Principal principal,
@PathVariable String sessionIdToDelete) {
Set<String> usersSessionIds = this.sessions.findByIndexNameAndIndexValue(
FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
public String removeSession(Principal principal, @PathVariable String sessionIdToDelete) {
Set<String> usersSessionIds = sessions.findByIndexNameAndIndexValue(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME,
principal.getName()).keySet();
if (usersSessionIds.contains(sessionIdToDelete)) {
this.sessions.delete(sessionIdToDelete);
if(usersSessionIds.contains(sessionIdToDelete)) {
sessions.delete(sessionIdToDelete);
}
return "redirect:/";
}
}
}

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.mvc;
import org.springframework.stereotype.Controller;

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.session;
import java.io.Serializable;
@@ -31,7 +30,7 @@ public class SessionDetails implements Serializable {
private String accessType;
public String getLocation() {
return this.location;
return location;
}
public void setLocation(String location) {
@@ -39,7 +38,7 @@ public class SessionDetails implements Serializable {
}
public String getAccessType() {
return this.accessType;
return accessType;
}
public void setAccessType(String accessType) {

View File

@@ -1,11 +1,11 @@
/*
* Copyright 2014-2016 the original author or authors.
* 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
*
* https://www.apache.org/licenses/LICENSE-2.0
* 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,
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sample.session;
import java.io.IOException;
@@ -25,20 +24,20 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.CityResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.CityResponse;
/**
* Inserts the session details into the session for every request. Some users may prefer
* to insert session details only after authentication. This is fine, but it may be
* valuable to the most up to date information so that if someone stole the user's session
* id it can be observed.
* Inserts the session details into the session for every request. Some users
* may prefer to insert session details only after authentication. This is fine,
* but it may be valuable to the most up to date information so that if someone
* stole the user's session id it can be observed.
*
* @author Rob Winch
*
@@ -57,8 +56,8 @@ public class SessionDetailsFilter extends OncePerRequestFilter {
}
// tag::dofilterinternal[]
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
HttpSession session = request.getSession(false);
@@ -77,21 +76,18 @@ public class SessionDetailsFilter extends OncePerRequestFilter {
String getGeoLocation(String remoteAddr) {
try {
CityResponse city = this.reader.city(InetAddress.getByName(remoteAddr));
CityResponse city = reader.city(InetAddress.getByName(remoteAddr));
String cityName = city.getCity().getName();
String countryName = city.getCountry().getName();
if (cityName == null && countryName == null) {
if(cityName == null && countryName == null) {
return null;
}
else if (cityName == null) {
} else if(cityName == null) {
return countryName;
}
else if (countryName == null) {
} else if(countryName == null) {
return cityName;
}
return cityName + ", " + countryName;
}
catch (Exception e) {
} catch (Exception e) {
return UNKNOWN;
}
@@ -101,11 +97,11 @@ public class SessionDetailsFilter extends OncePerRequestFilter {
String remoteAddr = request.getHeader("X-FORWARDED-FOR");
if (remoteAddr == null) {
remoteAddr = request.getRemoteAddr();
}
else if (remoteAddr.contains(",")) {
} else if (remoteAddr.contains(",")) {
remoteAddr = remoteAddr.split(",")[0];
}
return remoteAddr;
}
}
// end::class[]
//end::class[]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
<html xmlns:th="https://www.thymeleaf.org" xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect" layout:decorator="layout">
<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorator="layout">
<head>
<title>Secured Content</title>
</head>

View File

@@ -1,11 +1,11 @@
<!DOCTYPE html SYSTEM "https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
<!DOCTYPE html SYSTEM "http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="https://www.thymeleaf.org"
xmlns:layout="https://github.com/ultraq/thymeleaf-layout-dialect">
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<head>
<title layout:title-pattern="$DECORATOR_TITLE - $CONTENT_TITLE">Spring Session Sample</title>
<link rel="icon" type="image/x-icon" th:href="@{/resources/img/favicon.ico}" href="../static/img/favicon.ico"/>
<link th:href="@{/webjars/bootstrap/2.3.2/css/bootstrap.min.css}" href="/webjars/bootstrap/2.3.2/css/bootstrap.min.css" rel="stylesheet"></link>
<link th:href="@{/resources/css/bootstrap.css}" href="../static/css/bootstrap.css" rel="stylesheet"></link>
<style type="text/css">
/* Sticky footer styles
-------------------------------------------------- */
@@ -65,11 +65,11 @@
margin-left: 1em;
}
</style>
<link th:href="@{/webjars/bootstrap/2.3.2/css/bootstrap-responsive.min.css}" href="/webjars/bootstrap/2.3.2/css/bootstrap-responsive.min.css" rel="stylesheet"></link>
<link th:href="@{resources/css/bootstrap-responsive.css}" href="/static/css/bootstrap-responsive.css" rel="stylesheet"></link>
<!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
<!--[if lt IE 9]>
<script th:src="@{/webjars/html5shiv/3.7.3/html5shiv.min.js}" src="/webjars/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</head>
@@ -115,8 +115,8 @@
<div id="footer">
<div class="container">
<p class="muted credit">This product includes GeoLite2 data created by MaxMind, available from <a href="https://www.maxmind.com">https://www.maxmind.com</a>.</p>
<p class="muted credit">This product includes GeoLite2 data created by MaxMind, available from <a href="http://www.maxmind.com">http://www.maxmind.com</a>.</p>
</div>
</div>
</body>
</html>
</html>

Some files were not shown because too many files have changed in this diff Show More