Compare commits

..

41 Commits
1.3.x ... 1.4.x

Author SHA1 Message Date
Spring Operator
8cf73b73a7 URL Cleanup (#1385)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* [ ] http://www.puppycrawl.com/dtds/configuration_1_3.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/configuration_1_3.dtd ([https](https://www.puppycrawl.com/dtds/configuration_1_3.dtd) result 404).
* [ ] http://www.puppycrawl.com/dtds/suppressions_1_1.dtd (404) with 1 occurrences migrated to:
  https://www.puppycrawl.com/dtds/suppressions_1_1.dtd ([https](https://www.puppycrawl.com/dtds/suppressions_1_1.dtd) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://www.springframework.org/schema/beans/spring-beans.xsd with 13 occurrences migrated to:
  https://www.springframework.org/schema/beans/spring-beans.xsd ([https](https://www.springframework.org/schema/beans/spring-beans.xsd) result 200).
* [ ] http://www.springframework.org/schema/context/spring-context.xsd with 10 occurrences migrated to:
  https://www.springframework.org/schema/context/spring-context.xsd ([https](https://www.springframework.org/schema/context/spring-context.xsd) result 200).
* [ ] http://www.springframework.org/schema/gemfire/spring-gemfire.xsd with 4 occurrences migrated to:
  https://www.springframework.org/schema/gemfire/spring-gemfire.xsd ([https](https://www.springframework.org/schema/gemfire/spring-gemfire.xsd) result 200).
* [ ] http://www.springframework.org/schema/jdbc/spring-jdbc.xsd with 1 occurrences migrated to:
  https://www.springframework.org/schema/jdbc/spring-jdbc.xsd ([https](https://www.springframework.org/schema/jdbc/spring-jdbc.xsd) result 200).
* [ ] http://www.springframework.org/schema/security/spring-security.xsd with 2 occurrences migrated to:
  https://www.springframework.org/schema/security/spring-security.xsd ([https](https://www.springframework.org/schema/security/spring-security.xsd) result 200).
* [ ] http://www.springframework.org/schema/util/spring-util-4.1.xsd with 2 occurrences migrated to:
  https://www.springframework.org/schema/util/spring-util-4.1.xsd ([https](https://www.springframework.org/schema/util/spring-util-4.1.xsd) result 200).
* [ ] http://www.springframework.org/schema/util/spring-util.xsd with 4 occurrences migrated to:
  https://www.springframework.org/schema/util/spring-util.xsd ([https](https://www.springframework.org/schema/util/spring-util.xsd) result 200).
* [ ] http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd with 4 occurrences migrated to:
  https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd ([https](https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd) result 302).

# Ignored
These URLs were intentionally ignored.

* http://java.sun.com/xml/ns/javaee with 8 occurrences
* http://www.hazelcast.com/schema/config with 4 occurrences
* http://www.springframework.org/schema/beans with 26 occurrences
* http://www.springframework.org/schema/context with 20 occurrences
* http://www.springframework.org/schema/gemfire with 8 occurrences
* http://www.springframework.org/schema/jdbc with 2 occurrences
* http://www.springframework.org/schema/p with 8 occurrences
* http://www.springframework.org/schema/security with 4 occurrences
* http://www.springframework.org/schema/util with 12 occurrences
* http://www.w3.org/2001/XMLSchema-instance with 19 occurrences
2019-04-01 10:24:10 -05:00
Spring Operator
f1d795e3b5 URL Cleanup (#1391)
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# HTTP URLs that Could Not Be Fixed
These URLs were unable to be fixed. Please review them to see if they can be manually resolved.

* [ ] http://www.faqs.org/qa/rfcc-1940.html (200) with 3 occurrences could not be migrated:
   ([https](https://www.faqs.org/qa/rfcc-1940.html) result AnnotatedConnectException).
* [ ] http://www.faqs.org/rfcs/rfc3548.html (200) with 3 occurrences could not be migrated:
   ([https](https://www.faqs.org/rfcs/rfc3548.html) result AnnotatedConnectException).
* [ ] http://www.faqs.org/ (301) with 1 occurrences could not be migrated:
   ([https](https://www.faqs.org/) result AnnotatedConnectException).
* [ ] http://www.somehost.com/some/path (302) with 4 occurrences could not be migrated:
   ([https](https://www.somehost.com/some/path) result ConnectTimeoutException).
* [ ] http://www.somehost.com/some/path?%s=5 (302) with 2 occurrences could not be migrated:
   ([https](https://www.somehost.com/some/path?%s=5) result ConnectTimeoutException).
* [ ] http://www.somehost.com/some/path?a=b (302) with 4 occurrences could not be migrated:
   ([https](https://www.somehost.com/some/path?a=b) result ConnectTimeoutException).
* [ ] http://www.somehost.com/some/path?a=b&%s=5&c=d (302) with 2 occurrences could not be migrated:
   ([https](https://www.somehost.com/some/path?a=b&%s=5&c=d) result ConnectTimeoutException).
* [ ] http://iharder.net/base64 (303) with 2 occurrences could not be migrated:
   ([https](https://iharder.net/base64) result AnnotatedConnectException).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* [ ] http://www.ultraq.net.nz/thymeleaf/layout (302) with 14 occurrences migrated to:
  https://github.com/ultraq/thymeleaf-layout-dialect ([https](https://www.ultraq.net.nz/thymeleaf/layout) result ConnectTimeoutException).
* [ ] http://192.168.1.100:8080/ (AnnotatedConnectException) with 1 occurrences migrated to:
  https://192.168.1.100:8080/ ([https](https://192.168.1.100:8080/) result ConnectTimeoutException).
* [ ] http://www.faqs (UnknownHostException) with 1 occurrences migrated to:
  https://www.faqs ([https](https://www.faqs) result UnknownHostException).
* [ ] http://html5shim.googlecode.com/svn/trunk/html5.js (404) with 1 occurrences migrated to:
  https://html5shim.googlecode.com/svn/trunk/html5.js ([https](https://html5shim.googlecode.com/svn/trunk/html5.js) result 404).

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* [ ] http://creativecommons.org/licenses/by/3.0/ with 1 occurrences migrated to:
  https://creativecommons.org/licenses/by/3.0/ ([https](https://creativecommons.org/licenses/by/3.0/) result 200).
* [ ] http://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html with 2 occurrences migrated to:
  https://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html ([https](https://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html) result 200).
* [ ] http://docs.hazelcast.org/docs/latest/manual/html-single/index.html with 8 occurrences migrated to:
  https://docs.hazelcast.org/docs/latest/manual/html-single/index.html ([https](https://docs.hazelcast.org/docs/latest/manual/html-single/index.html) result 200).
* [ ] http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html with 1 occurrences migrated to:
  https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html ([https](https://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletResponse.html) result 200).
* [ ] http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/ with 4 occurrences migrated to:
  https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/ ([https](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/) result 200).
* [ ] http://docs.spring.io/spring-data-gemfire/docs/current/reference/html/ with 6 occurrences migrated to:
  https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/ ([https](https://docs.spring.io/spring-data-gemfire/docs/current/reference/html/) result 200).
* [ ] http://docs.spring.io/spring-data-redis/docs/current/reference/html/ with 1 occurrences migrated to:
  https://docs.spring.io/spring-data-redis/docs/current/reference/html/ ([https](https://docs.spring.io/spring-data-redis/docs/current/reference/html/) result 200).
* [ ] http://docs.spring.io/spring-data/data-redis/docs/current/reference/html/ with 5 occurrences migrated to:
  https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/ ([https](https://docs.spring.io/spring-data/data-redis/docs/current/reference/html/) result 200).
* [ ] http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html with 4 occurrences migrated to:
  https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html ([https](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/DelegatingFilterProxy.html) result 200).
* [ ] http://docs.spring.io/spring-security/site/docs/4.2.x/reference/htmlsingle/ with 1 occurrences migrated to:
  https://docs.spring.io/spring-security/site/docs/4.2.x/reference/htmlsingle/ ([https](https://docs.spring.io/spring-security/site/docs/4.2.x/reference/htmlsingle/) result 200).
* [ ] http://docs.spring.io/spring-session/docs/1.3.0.RELEASE/reference/html5/ with 2 occurrences migrated to:
  https://docs.spring.io/spring-session/docs/1.3.0.RELEASE/reference/html5/ ([https](https://docs.spring.io/spring-session/docs/1.3.0.RELEASE/reference/html5/) result 200).
* [ ] http://docs.spring.io/spring-session/docs/current/reference/html5/ with 1 occurrences migrated to:
  https://docs.spring.io/spring-session/docs/current/reference/html5/ ([https](https://docs.spring.io/spring-session/docs/current/reference/html5/) result 200).
* [ ] http://getbootstrap.com/getting-started/ with 1 occurrences migrated to:
  https://getbootstrap.com/getting-started/ ([https](https://getbootstrap.com/getting-started/) result 200).
* [ ] http://hazelcast.org/ with 1 occurrences migrated to:
  https://hazelcast.org/ ([https](https://hazelcast.org/) result 200).
* [ ] http://infinispan.org/docs/dev/user_guide/user_guide.html with 1 occurrences migrated to:
  https://infinispan.org/docs/dev/user_guide/user_guide.html ([https](https://infinispan.org/docs/dev/user_guide/user_guide.html) result 200).
* [ ] http://logback.qos.ch/manual/groovy.html with 1 occurrences migrated to:
  https://logback.qos.ch/manual/groovy.html ([https](https://logback.qos.ch/manual/groovy.html) result 200).
* [ ] http://projects.spring.io/spring-session/ with 1 occurrences migrated to:
  https://projects.spring.io/spring-session/ ([https](https://projects.spring.io/spring-session/) result 200).
* [ ] http://redis.io/commands with 1 occurrences migrated to:
  https://redis.io/commands ([https](https://redis.io/commands) result 200).
* [ ] http://redis.io/commands/expire with 1 occurrences migrated to:
  https://redis.io/commands/expire ([https](https://redis.io/commands/expire) result 200).
* [ ] http://redis.io/commands/hmset with 1 occurrences migrated to:
  https://redis.io/commands/hmset ([https](https://redis.io/commands/hmset) result 200).
* [ ] http://redis.io/download with 10 occurrences migrated to:
  https://redis.io/download ([https](https://redis.io/download) result 200).
* [ ] http://redis.io/topics/data-types with 1 occurrences migrated to:
  https://redis.io/topics/data-types ([https](https://redis.io/topics/data-types) result 200).
* [ ] http://redis.io/topics/notifications with 5 occurrences migrated to:
  https://redis.io/topics/notifications ([https](https://redis.io/topics/notifications) result 200).
* [ ] http://redis.io/topics/quickstart with 7 occurrences migrated to:
  https://redis.io/topics/quickstart ([https](https://redis.io/topics/quickstart) result 200).
* [ ] http://stackoverflow.com with 1 occurrences migrated to:
  https://stackoverflow.com ([https](https://stackoverflow.com) result 200).
* [ ] http://stackoverflow.com/questions/tagged/spring-session with 1 occurrences migrated to:
  https://stackoverflow.com/questions/tagged/spring-session ([https](https://stackoverflow.com/questions/tagged/spring-session) result 200).
* [ ] http://stackoverflow.com/tags/spring-session with 1 occurrences migrated to:
  https://stackoverflow.com/tags/spring-session ([https](https://stackoverflow.com/tags/spring-session) result 200).
* [ ] http://www.thymeleaf.org with 15 occurrences migrated to:
  https://www.thymeleaf.org ([https](https://www.thymeleaf.org) result 200).
* [ ] http://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd with 7 occurrences migrated to:
  https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd ([https](https://www.thymeleaf.org/dtd/xhtml1-strict-thymeleaf-spring4-3.dtd) result 200).
* [ ] http://contributor-covenant.org with 1 occurrences migrated to:
  https://contributor-covenant.org ([https](https://contributor-covenant.org) result 301).
* [ ] http://contributor-covenant.org/version/1/3/0/ with 1 occurrences migrated to:
  https://contributor-covenant.org/version/1/3/0/ ([https](https://contributor-covenant.org/version/1/3/0/) result 301).
* [ ] http://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html with 5 occurrences migrated to:
  https://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html ([https](https://docs.spring.io/spring/docs/current/spring-framework-reference/html/spring-data-tier.html) result 301).
* [ ] http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/ with 4 occurrences migrated to:
  https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/ ([https](https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/function_exec/chapter_overview.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/function_exec/chapter_overview.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/function_exec/chapter_overview.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html with 5 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/management_all_region_types/chapter_overview.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/creating_map_indexes.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/creating_map_indexes.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/creating_map_indexes.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/query_index.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/query_index.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/developing/query_index/query_index.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html with 5 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/product_intro.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/product_intro.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/product_intro.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html with 2 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/management/membership/ClientMembershipListener.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/management/membership/ClientMembershipListener.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/management/membership/ClientMembershipListener.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html with 5 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/tools_modules/gfsh/chapter_overview.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html with 4 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/cs_configuration/chapter_overview.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/p2p_configuration/chapter_overview.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/p2p_configuration/chapter_overview.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/latest/topologies_and_comm/p2p_configuration/chapter_overview.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html with 3 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html) result 302).
* [ ] http://gemfire.docs.pivotal.io/docs-gemfire/topologies_and_comm/multi_site_configuration/chapter_overview.html with 1 occurrences migrated to:
  https://gemfire.docs.pivotal.io/docs-gemfire/topologies_and_comm/multi_site_configuration/chapter_overview.html ([https](https://gemfire.docs.pivotal.io/docs-gemfire/topologies_and_comm/multi_site_configuration/chapter_overview.html) result 302).
* [ ] http://spring.io/spring-security with 4 occurrences migrated to:
  https://spring.io/spring-security ([https](https://spring.io/spring-security) result 302).
* [ ] http://www.maxmind.com with 3 occurrences migrated to:
  https://www.maxmind.com ([https](https://www.maxmind.com) result 302).

# Ignored
These URLs were intentionally ignored.

* http://java.sun.com/jsp/jstl/core with 14 occurrences
* http://localhost with 21 occurrences
* http://localhost:8080/ with 45 occurrences
* http://localhost:8080/?_s=0 with 1 occurrences
* http://localhost:8080/?_s=1 with 2 occurrences
* http://localhost:8080/h2-console/ with 3 occurrences
* http://localhost:8080/logout with 1 occurrences
* http://localhost:8080/test/index with 2 occurrences
* http://localhost:xxxxx/hazelcast/rest/maps/spring:session:sessions/7e8383a4-082c-4ffe-a4bc-c40fd3363c5e with 1 occurrences
* http://www.w3.org/1999/xhtml with 7 occurrences
* http://www.webjars.org/tags with 14 occurrences
2019-04-01 10:22:19 -05:00
Spring Operator
2465c2b40e URL Cleanup
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortener).

# Fixed URLs

## Fixed Success
These URLs were switched to an https URL with a 2xx status. While the status was successful, your review is still recommended.

* http://www.apache.org/licenses/LICENSE-2.0 with 336 occurrences migrated to:
  https://www.apache.org/licenses/LICENSE-2.0 ([https](https://www.apache.org/licenses/LICENSE-2.0) result 200).
* http://www.apache.org/licenses/LICENSE-2.0.html with 2 occurrences migrated to:
  https://www.apache.org/licenses/LICENSE-2.0.html ([https](https://www.apache.org/licenses/LICENSE-2.0.html) result 200).
2019-03-14 20:38:38 -05:00
Rob Winch
3988f7a046 URL Cleanup
This commit updates URLs to prefer the https protocol. Redirects are not followed to avoid accidentally expanding intentionally shortened URLs (i.e. if using a URL shortner).

# HTTP URLs that Could Not Be Fixed
These URLs were unable to be fixed. Please review them to see if they can be manually resolved.

* http://aopalliance.sourceforge.net/doc/ (200) migrated to:
  http://aopalliance.sourceforge.net/doc/ ([https](https://aopalliance.sourceforge.net/doc/) result AnnotatedConnectException).
* http://dist.gemstone.com/maven/release (404) migrated to:
  http://dist.gemstone.com/maven/release ([https](https://dist.gemstone.com/maven/release) result SSLHandshakeException).

# Fixed URLs

## Fixed But Review Recommended
These URLs were fixed, but the https status was not OK. However, the https status was the same as the http request or http redirected to an https URL, so they were migrated. Your review is recommended.

* http://www.quartz-scheduler.org/api/2.2.0/ (404) migrated to:
  https://www.quartz-scheduler.org/api/2.2.0/ ([https](https://www.quartz-scheduler.org/api/2.2.0/) result 404).

## Fixed Success
These URLs were fixed successfully.

* http://commons.apache.org/proper/commons-codec/apidocs/ migrated to:
  https://commons.apache.org/proper/commons-codec/apidocs/ ([https](https://commons.apache.org/proper/commons-codec/apidocs/) result 200).
* http://commons.apache.org/proper/commons-dbcp/apidocs/ migrated to:
  https://commons.apache.org/proper/commons-dbcp/apidocs/ ([https](https://commons.apache.org/proper/commons-dbcp/apidocs/) result 200).
* http://commons.apache.org/proper/commons-lang/javadocs/api-2.5/ migrated to:
  https://commons.apache.org/proper/commons-lang/javadocs/api-2.5/ ([https](https://commons.apache.org/proper/commons-lang/javadocs/api-2.5/) result 200).
* http://docs.jboss.org/jbossas/javadoc/4.0.5/connector/ migrated to:
  https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/ ([https](https://docs.jboss.org/jbossas/javadoc/4.0.5/connector/) result 200).
* http://docs.jboss.org/jbossas/javadoc/7.1.2.Final/ migrated to:
  https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/ ([https](https://docs.jboss.org/jbossas/javadoc/7.1.2.Final/) result 200).
* http://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/ migrated to:
  https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/ ([https](https://docs.oracle.com/cd/E13222_01/wls/docs90/javadocs/) result 200).
* http://docs.oracle.com/javaee/7/api/ migrated to:
  https://docs.oracle.com/javaee/7/api/ ([https](https://docs.oracle.com/javaee/7/api/) result 200).
* http://docs.oracle.com/javase/8/docs/api/ migrated to:
  https://docs.oracle.com/javase/8/docs/api/ ([https](https://docs.oracle.com/javase/8/docs/api/) result 200).
* http://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/ migrated to:
  https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/ ([https](https://hc.apache.org/httpcomponents-client-ga/httpclient/apidocs/) result 200).
* http://portals.apache.org/pluto/portlet-2.0-apidocs/ migrated to:
  https://portals.apache.org/pluto/portlet-2.0-apidocs/ ([https](https://portals.apache.org/pluto/portlet-2.0-apidocs/) result 200).
* http://tiles.apache.org/framework/apidocs/ migrated to:
  https://tiles.apache.org/framework/apidocs/ ([https](https://tiles.apache.org/framework/apidocs/) result 200).
* http://tiles.apache.org/tiles-request/apidocs/ migrated to:
  https://tiles.apache.org/tiles-request/apidocs/ ([https](https://tiles.apache.org/tiles-request/apidocs/) result 200).
* http://www.apache.org/licenses/LICENSE-2.0.txt migrated to:
  https://www.apache.org/licenses/LICENSE-2.0.txt ([https](https://www.apache.org/licenses/LICENSE-2.0.txt) result 200).
* http://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/ migrated to:
  https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/ ([https](https://www.eclipse.org/aspectj/doc/released/aspectj5rt-api/) result 200).
* http://fasterxml.github.com/jackson-core/javadoc/2.3.0/ migrated to:
  https://fasterxml.github.com/jackson-core/javadoc/2.3.0/ ([https](https://fasterxml.github.com/jackson-core/javadoc/2.3.0/) result 301).
* http://fasterxml.github.com/jackson-databind/javadoc/2.3.0/ migrated to:
  https://fasterxml.github.com/jackson-databind/javadoc/2.3.0/ ([https](https://fasterxml.github.com/jackson-databind/javadoc/2.3.0/) result 301).
* http://glassfish.java.net/nonav/docs/v3/api/ migrated to:
  https://glassfish.java.net/nonav/docs/v3/api/ ([https](https://glassfish.java.net/nonav/docs/v3/api/) result 301).
* http://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/ migrated to:
  https://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/ ([https](https://pic.dhe.ibm.com/infocenter/wasinfo/v7r0/topic/com.ibm.websphere.javadoc.doc/web/apidocs/) result 301).
* http://projects.spring.io/spring-session migrated to:
  https://projects.spring.io/spring-session ([https](https://projects.spring.io/spring-session) result 301).
2019-03-05 08:30:08 -06:00
Vedran Pavic
78dce3d72a Add support for configuring default CookieSerializer using SessionCookieConfig
Fixes gh-807
2017-06-23 12:22:04 +02:00
Vedran Pavic
32944312ed Upgrade dependencies
This commit upgrades project dependencies to Spring Boot 1.5.4.RELEASE and Spring IO Platform Brussels-SR3 levels.

Fixes gh-808
2017-06-23 12:22:04 +02:00
Vedran Pavic
786a620bef Replace StringBuffer usages with StringBuilder
Fixes gh-794
2017-05-30 22:57:32 +02:00
Vedran Pavic
a03cb02536 Parameterize SpringSessionBackedSessionRegistry
Fixes gh-781
2017-05-13 12:30:19 +02:00
Vedran Pavic
16abdc5e5c Deprecate Mongo
Fixes gh-773
2017-05-07 10:43:05 +02:00
Vedran Pavic
fd55882a6e Deprecate GemFire
Fixes gh-773
2017-05-07 10:32:53 +02:00
Vedran Pavic
62ed0cde4c Fix broken documentation links 2017-04-29 10:23:07 +02:00
Vedran Pavic
2d2e7a3cec Use explicit constraints in JDBC schema scripts
Fixes gh-766
2017-04-26 23:32:58 +02:00
Rob Winch
6e2d4a5ef4 SpringSessionRememberMeServices rm SecurityContext attribute
SpringSessionRememberMeServices use to invalidate the session which would
cause Spring Security's saved request to be lost.

Now SpringSessionRememberMeServices deletes the SecurityContext from the
HttpSession instead.

Fixes gh-752
2017-04-26 08:57:55 -05:00
John Blum
808414191e Upgrade to Spring Data Redis 1.8.3.RELEASE
Fixed gh-756
2017-04-25 20:23:54 -07:00
John Blum
c0c404ab96 Restore proper behavior of HttpSession created events in GemFire support when client Region is a PROXY in the client/server topology
Fixes gh-757

(cherry picked from commit 432eb84a94)
Signed-off-by: John Blum <jblum@pivotal.io>
2017-04-25 20:21:47 -07:00
John Blum
dcc0c07981 Improve GemFire SessionRepository, Session copy logic to avoid issues with delta propagation on updates
Upgrade to Spring Data GemFire 1.9.3.RELEASE

Fixes #gh-755

(cherry picked from commit 6668e41b0a)
Signed-off-by: John Blum <jblum@pivotal.io>
2017-04-21 17:21:30 -07:00
Vedran Pavic
87bf8e194b Fix typo in .gitignore 2017-03-23 22:22:45 +01:00
Vedran Pavic
7ef73a283f Remove logging for "Skip invoking on" response committed
Fixes gh-747
2017-03-23 22:22:24 +01:00
Sebastian Laskawiec
70939bd349 Add link to Infinispan for Spring Session documentation
Fixes gh-746
2017-03-23 22:21:54 +01:00
Rob Winch
2b7a13eae9 Use Brussels-SR1 2017-03-21 13:04:39 -05:00
John Blum
4175751b1b Introduce more reliable coordination between a GemFire client/server during integration tests.
Fixes gh-728
2017-02-16 22:08:36 +01:00
John Blum
736b341ba3 Fixes GemFire client/server integratione tests issue when setting JAVA_TOOL_OPTIONS env var
Fixes gh-727
2017-02-16 20:51:58 +01:00
Vedran Pavic
ecf0a80d7d Backport GemFire improvements 2017-02-16 20:35:31 +01:00
John Blum
0a7e0f1a97 Fix invalid not null assertions
Fixes gh-726
2017-02-02 20:47:19 +01:00
Vedran Pavic
32d928564c Prevent NPE inMongoOperationsSessionRepository when creating session if max inactive interval is undefined
Fixes gh-717
2017-01-21 23:42:05 +01:00
Vedran Pavic
bbd731a835 Improve Hazelcast support documentation
Fixes gh-715
2017-01-17 21:42:05 +01:00
Rob Winch
bdc4756cb4 Polish 2017-01-16 16:35:39 -06:00
Vedran Pavic
1b6dd3f0fd Restructure samples 2017-01-16 16:35:31 -06:00
Rob Winch
ae2b3d8ed2 Polish Brussels Changes
Issue gh-708
2017-01-13 12:29:34 -06:00
Rob Winch
5cbabfb719 Fix Brussels Build
- Update Spring IO plugin to resolve binary incompatability for tests
- Update Dependency Management Plugin which is required for Spring IO
  plugin update
- Update to Spring Boot 1.5.0.RC1. Necessary because new dependency
  management plugin does not work with Boot 1.4.x

Fixes gh-708
2017-01-13 11:28:18 -06:00
Vedran Pavic
a25f6c38e0 Fix Gradle deprecation warnings
(cherry picked from commit 41fbc90)
2017-01-12 22:17:25 +01:00
Eddú Meléndez
e192cae078 Polish samples
Fixes gh-705
2017-01-12 21:33:53 +01:00
Vedran Pavic
7a138ea1ca Use capitalized words for HeaderHttpSessionStrategy default header name
Fixes gh-704
2017-01-12 21:32:21 +01:00
Rob Winch
11d9c708fd Fix Buildship import with eclipse.jdt.javaRuntimeName
See https://discuss.gradle.org/t/building-with-newer-jdks/21102
2017-01-12 21:30:44 +01:00
Rob Winch
69ea274754 Update to Gradle 3.3 2017-01-12 21:30:23 +01:00
Vedran Pavic
93be87ed94 Polish XPath expressions in samples integration tests 2017-01-11 22:57:23 +01:00
Vedran Pavic
01e4664681 Fix integration tests for GemFire based samples
Fixes gh-703
2017-01-11 22:08:08 +01:00
Rob Winch
d7c29652e7 Polish contribution 2017-01-11 18:54:10 +01:00
Pool Dolorier
5c031989a8 Move groovy test to java 2017-01-11 18:38:47 +01:00
Eddú Meléndez
8f71ace84c Convert groovy tests to java 2017-01-11 18:38:35 +01:00
Rob Winch
9c236fa256 Start 1.4.x 2016-12-19 13:38:08 -06:00
426 changed files with 6273 additions and 3945 deletions

2
.gitignore vendored
View File

@@ -10,5 +10,5 @@ target
out
.springBeans
*.rdb
!eclipse/.checkstyle
.checkstyle
!etc/eclipse/.checkstyle

View File

@@ -1,12 +1,13 @@
buildscript {
repositories {
maven { url "https://repo.spring.io/plugins-release" }
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
classpath 'io.spring.gradle:dependency-management-plugin:0.6.1.RELEASE'
classpath 'io.spring.gradle:dependency-management-plugin:1.0.3.RELEASE'
classpath("com.bmuschko:gradle-tomcat-plugin:2.2.5")
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.7")
classpath("io.spring.gradle:spring-io-plugin:0.0.4.RELEASE")
classpath("io.spring.gradle:spring-io-plugin:0.0.6.RELEASE")
classpath('me.champeau.gradle:gradle-javadoc-hotfix-plugin:0.1')
classpath 'org.asciidoctor:asciidoctor-gradle-plugin:1.5.2'
classpath 'com.github.ben-manes:gradle-versions-plugin:0.12.0'
@@ -19,10 +20,9 @@ plugins {
group = 'org.springframework.session'
ext.springBootVersion = '1.4.7.RELEASE'
ext.springBootVersion = '1.5.4.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.BOM_GRADLE = "$rootDir/gradle/bom.gradle"
ext.SAMPLE_GRADLE = "$rootDir/gradle/sample.gradle"

View File

@@ -50,7 +50,7 @@ dependencies {
asciidoctor {
def ghTag = snapshotBuild ? 'master' : project.version
def ghUrl = "https://github.com/spring-projects/spring-session/tree/$ghTag/"
def ghUrl = "https://github.com/spring-projects/spring-session/tree/$ghTag"
attributes 'version-snapshot': snapshotBuild,
'version-milestone': milestoneBuild,
'version-release': releaseBuild,
@@ -76,3 +76,5 @@ asciidoctor {
'docinfo1':'true',
'revnumber' : project.version
}
eclipse.project.name = 'spring-session-docs'

View File

@@ -65,7 +65,7 @@ For example, our sample application includes the location and access type of the
[source,java,indent=0]
----
include::{samples-dir}findbyusername/src/main/java/sample/session/SessionDetails.java[tags=class]
include::{samples-dir}boot/findbyusername/src/main/java/sample/session/SessionDetails.java[tags=class]
----
We then inject that information into the session on each HTTP request using a `SessionDetailsFilter`.
@@ -73,7 +73,7 @@ For example:
[source,java,indent=0]
----
include::{samples-dir}findbyusername/src/main/java/sample/session/SessionDetailsFilter.java[tags=dofilterinternal]
include::{samples-dir}boot/findbyusername/src/main/java/sample/session/SessionDetailsFilter.java[tags=dofilterinternal]
----
We obtain the information we want and then set the `SessionDetails` as an attribute in the `Session`.
@@ -93,7 +93,7 @@ We can now find all the sessions for a specific user.
[source,java,indent=0]
----
include::{samples-dir}findbyusername/src/main/java/sample/mvc/IndexController.java[tags=findbyusername]
include::{samples-dir}boot/findbyusername/src/main/java/sample/mvc/IndexController.java[tags=findbyusername]
----
In our instance, we find all sessions for the currently logged in user.

View File

@@ -86,7 +86,7 @@ We start with the _Spring Boot_ application for configuring and bootstrapping a
[source,java]
----
include::{samples-dir}httpsession-gemfire-boot/src/main/java/sample/server/GemFireServer.java[tags=class]
include::{samples-dir}boot/gemfire/src/main/java/sample/server/GemFireServer.java[tags=class]
----
<1> The `@EnableGemFireHttpSession` annotation is used on the GemFire Server to mainly define the corresponding
@@ -95,7 +95,7 @@ and managed by GemFire. As well, we have specified an arbitrary expiration attr
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` that allow us to configure certain aspects of the GemFire Server using
https://gemfire.docs.pivotal.io/docs-gemfire/latest/reference/topics/gemfire_properties.html[GemFire's System properties].
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 configure and start a `CacheServer` running in the GemFire Server to listen for connections
from cache clients. The `CacheServer's` `Socket` will be used to connect our GemFire cache client,
@@ -113,7 +113,7 @@ to manage Session state in a clustered, replicated fashion.
[source,java]
----
include::{samples-dir}httpsession-gemfire-boot/src/main/java/sample/client/Application.java[tags=class]
include::{samples-dir}boot/gemfire/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,
@@ -159,7 +159,7 @@ 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://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
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.
* `poolName` - name of the dedicated GemFire Pool used to connect a client to the cluster of servers. The attribute
is only used when the application is a GemFire cache client. Defaults to `gemfirePool`.
@@ -230,7 +230,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/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
see https://gemfire.docs.pivotal.io/docs-gemfire/latest/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
NOTE: In order to run the following, you must uncomment the lines in the `GemFireServer` class, `gemfireProperties` bean
for the following GemFire System properties: `jmx-manager` and `jmx-manager-start`.

View File

@@ -74,7 +74,7 @@ Add the following Spring Configuration:
[source,java]
----
include::{samples-dir}httpsession-jdbc-boot/src/main/java/sample/config/HttpSessionConfig.java[tags=class]
include::{samples-dir}boot/jdbc/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.

View File

@@ -75,7 +75,7 @@ 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]
include::{samples-dir}boot/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.

View File

@@ -25,7 +25,7 @@ If you are using Maven, ensure to add the following dependencies:
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<artifactId>spring-boot-starter-redis</artifactId>
</dependency>
</dependencies>
----
@@ -72,7 +72,7 @@ Add the following Spring Configuration:
[source,java]
----
include::{samples-dir}boot/src/main/java/sample/config/HttpSessionConfig.java[tags=class]
include::{samples-dir}boot/redis/src/main/java/sample/config/HttpSessionConfig.java[tags=class]
----
<1> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter.

View File

@@ -38,7 +38,7 @@ For example:
.src/main/java/samples/config/WebSocketConfig.java
[source,java]
----
include::{samples-dir}websocket/src/main/java/sample/config/WebSocketConfig.java[tags=class]
include::{samples-dir}boot/websocket/src/main/java/sample/config/WebSocketConfig.java[tags=class]
----
To hook in the Spring Session support we only need to change two things:
@@ -78,7 +78,7 @@ For the purposes of testing session expiration, you may want to change the sessi
.src/main/java/samples/config/WebSecurityConfig.java
[source,java]
----
include::{samples-dir}websocket/src/main/java/sample/config/WebSecurityConfig.java[tags=enable-redis-httpsession]
include::{samples-dir}boot/websocket/src/main/java/sample/config/WebSecurityConfig.java[tags=enable-redis-httpsession]
----
====

View File

@@ -127,6 +127,3 @@ Alternatively, you can also delete the explicit key. Enter the following into yo
$ 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.
NOTE: Spring Session will not work with grails flash scope without additional work. +
See this answer for an explanation: https://stackoverflow.com/a/43311427

View File

@@ -17,7 +17,7 @@ You can find an example of customizing Spring Session's cookie below:
[source,java]
----
include::{samples-dir}custom-cookie/src/main/java/sample/Config.java[tags=cookie-serializer]
include::{samples-dir}javaconfig/custom-cookie/src/main/java/sample/Config.java[tags=cookie-serializer]
----
<1> We customize the name of the cookie to be JSESSIONID
@@ -98,4 +98,4 @@ Try using the application. Fill out the form with the following information:
Now click the **Set Attribute** button.
You should now see the values displayed in the table.
If you look at the cookies for the application, you can see the cookie is saved to the custom name of JSESSIONID
If you look at the cookies for the application, you can see the cookie is saved to the custom name of JSESSIONID

View File

@@ -80,27 +80,27 @@ Add the following Spring Configuration:
[source,java]
----
include::{samples-dir}httpsession-gemfire-clientserver/src/main/java/sample/ClientConfig.java[tags=class]
include::{samples-dir}javaconfig/gemfire-clientserver/src/main/java/sample/ClientConfig.java[tags=class]
----
<1> The `@EnableGemFireHttpSession` annotation creates a Spring bean named `springSessionRepositoryFilter` that
implements `Filter`. The filter is what replaces the `HttpSession` with an implementation backed by Spring Session
and 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/latest/reference/topics/gemfire_properties.html[GemFire's System properties].
using https://gemfire.docs.pivotal.io/docs-gemfire/reference/topics/gemfire_properties.html[GemFire's System properties].
<3> We use the `Properties` to configure an instance of a GemFire `ClientCache`.
<4> 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://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html[PoolFactory API].
<56> Finally, we include a Spring `BeanPostProcessor` to block the client until our GemFire Server is up and running,
https://gemfire.docs.pivotal.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/PoolFactory.html[PoolFactory API].
<5> Finally, we include a Spring `BeanPostProcessor` to block the client until our GemFire Server is up and running,
listening for and accepting client connections.
The `gemfireCacheServerReadyBeanPostProcessor` is necessary in order to coordinate the client and server in
an automated fashion during testing, but unnecessary in situations where the GemFire cluster is already presently
running, such as in production.
The `BeanPostProcessor` uses a GemFire https://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/management/membership/ClientMembershipListener.html[ClientMembershipListener]
The `BeanPostProcessor` uses a GemFire https://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.
@@ -118,7 +118,7 @@ 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://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/client/ClientRegionShortcut.html[ClientRegionShortcut]
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.
* `poolName` - name of the dedicated GemFire Pool used to connect a client to the cluster of servers. The attribute
is only used when the application is a GemFire cache client. Defaults to `gemfirePool`.
@@ -144,7 +144,7 @@ In this sample, we will use the following GemFire Server Java Configuration:
[source,java]
----
include::{samples-dir}httpsession-gemfire-clientserver/src/main/java/sample/ServerConfig.java[tags=class]
include::{samples-dir}javaconfig/gemfire-clientserver/src/main/java/sample/ServerConfig.java[tags=class]
----
<1> On the server, we also configure Spring Session using the `@EnableGemFireHttpSession` annotation. This ensures
@@ -174,7 +174,7 @@ You can find an example below:
.src/main/java/sample/Initializer.java
[source,java]
----
include::{samples-dir}httpsession-gemfire-clientserver/src/main/java/sample/Initializer.java[tags=class]
include::{samples-dir}javaconfig/gemfire-clientserver/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`.
@@ -224,7 +224,7 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
.src/main/java/sample/SessionServlet.java
[source,java]
----
include::{samples-dir}httpsession-gemfire-clientserver/src/main/java/sample/SessionServlet.java[tags=class]
include::{samples-dir}javaconfig/gemfire-clientserver/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in GemFire.
@@ -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/gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
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:

View File

@@ -80,7 +80,7 @@ Add the following Spring Configuration:
[source,java]
----
include::{samples-dir}httpsession-gemfire-p2p/src/main/java/sample/Config.java[tags=class]
include::{samples-dir}javaconfig/gemfire-p2p/src/main/java/sample/Config.java[tags=class]
----
<1> The `@EnableGemFireHttpSession` annotation creates a Spring bean named `springSessionRepositoryFilter` that
@@ -104,7 +104,7 @@ 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://data-docs-samples.cfapps.io/docs-gemfire/latest/javadocs/japi/com/gemstone/gemfire/cache/RegionShortcut.html[RegionShortcut]
with a GemFire https://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,
@@ -125,7 +125,7 @@ You can find an example below:
.src/main/java/sample/Initializer.java
[source,java]
----
include::{samples-dir}httpsession-gemfire-p2p/src/main/java/sample/Initializer.java[tags=class]
include::{samples-dir}javaconfig/gemfire-p2p/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`.
@@ -166,7 +166,7 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
.src/main/java/sample/SessionServlet.java
[source,java]
----
include::{samples-dir}httpsession-gemfire-p2p/src/main/java/sample/SessionServlet.java[tags=class]
include::{samples-dir}javaconfig/gemfire-p2p/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in GemFire.
@@ -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/gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
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:

View File

@@ -98,7 +98,7 @@ Since our application is already loading Spring configuration using our `Securit
.src/main/java/sample/SecurityInitializer.java
[source,java]
----
include::{samples-dir}hazelcast-spring/src/main/java/sample/SecurityInitializer.java[tags=class]
include::{samples-dir}javaconfig/hazelcast/src/main/java/sample/SecurityInitializer.java[tags=class]
----
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
@@ -110,7 +110,7 @@ You can find an example below:
.src/main/java/sample/Initializer.java
[source,java]
----
include::{samples-dir}hazelcast-spring/src/main/java/sample/Initializer.java[tags=class]
include::{samples-dir}javaconfig/hazelcast/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`.

View File

@@ -75,7 +75,7 @@ Add the following Spring Configuration:
[source,java]
----
include::{samples-dir}httpsession-jdbc/src/main/java/sample/Config.java[tags=class]
include::{samples-dir}javaconfig/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.
@@ -100,7 +100,7 @@ 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]
include::{samples-dir}javaconfig/jdbc/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`.
@@ -140,7 +140,7 @@ 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]
include::{samples-dir}javaconfig/jdbc/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in H2 database.

View File

@@ -80,7 +80,7 @@ Add the following Spring Configuration:
[source,java]
----
include::{samples-dir}httpsession/src/main/java/sample/Config.java[tags=class]
include::{samples-dir}javaconfig/redis/src/main/java/sample/Config.java[tags=class]
----
<1> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter.
@@ -103,7 +103,7 @@ 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]
include::{samples-dir}javaconfig/redis/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`.
@@ -151,7 +151,7 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
.src/main/java/sample/SessionServlet.java
[source,java]
----
include::{samples-dir}httpsession/src/main/java/sample/SessionServlet.java[tags=class]
include::{samples-dir}javaconfig/redis/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis.
@@ -168,4 +168,4 @@ Alternatively, you can also delete the explicit key. Enter the following into yo
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.

View File

@@ -80,7 +80,7 @@ Add the following Spring Configuration:
[source,java]
----
include::{samples-dir}rest/src/main/java/sample/HttpSessionConfig.java[tags=class]
include::{samples-dir}javaconfig/rest/src/main/java/sample/HttpSessionConfig.java[tags=class]
----
<1> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements `Filter`.
@@ -101,7 +101,7 @@ In order for our `Filter` to do its magic, Spring needs to load our `Config` cla
.src/main/java/sample/mvc/MvcInitializer.java
[source,java,indent=0]
----
include::{samples-dir}rest/src/main/java/sample/mvc/MvcInitializer.java[tags=config]
include::{samples-dir}javaconfig/rest/src/main/java/sample/mvc/MvcInitializer.java[tags=config]
----
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
@@ -110,7 +110,7 @@ Fortunately, Spring Session provides a utility class named `AbstractHttpSessionA
.src/main/java/sample/Initializer.java
[source,java]
----
include::{samples-dir}rest/src/main/java/sample/Initializer.java[tags=class]
include::{samples-dir}javaconfig/rest/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`.
@@ -154,7 +154,7 @@ In the output you will notice the following:
----
HTTP/1.1 200 OK
...
x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3
X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3
{"username":"user"}
----
@@ -162,25 +162,25 @@ x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3
Specifically, we notice the following things about our response:
* The HTTP Status is now a 200
* We have a header with the name of *x-auth-token* which contains a new session id
* 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 username just as before:
$ curl -v http://localhost:8080/ -H "x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
$ curl -v http://localhost:8080/ -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
The only difference is that the session id is not provided in the response headers because we are reusing an existing session.
If we invalidate the session, then the x-auth-token is displayed in the response with an empty value. For example, the following will invalidate our session:
If we invalidate the session, then the X-Auth-Token is displayed in the response with an empty value. For example, the following will invalidate our session:
$ curl -v http://localhost:8080/logout -H "x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
$ curl -v http://localhost:8080/logout -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
You will see in the output that the x-auth-token provides an empty String indicating that the previous session was invalidated.
You will see in the output that the X-Auth-Token provides an empty String indicating that the previous session was invalidated.
----
HTTP/1.1 204 No Content
...
x-auth-token:
X-Auth-Token:
----
=== How does it work?
@@ -188,7 +188,7 @@ x-auth-token:
Spring Security interacts with the standard `HttpSession` in `SecurityContextPersistenceFilter`.
Instead of using Tomcat's `HttpSession`, Spring Security is now persisting the values in Redis.
Spring Session creates a header named x-auth-token in your browser that contains the id of your session.
Spring Session creates a header named X-Auth-Token in your browser that contains the id of your session.
If you like, you can easily see that the session is created in Redis. First create a session using the following:
@@ -199,7 +199,7 @@ In the output you will notice the following:
----
HTTP/1.1 200 OK
...
x-auth-token: 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
X-Auth-Token: 7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
{"username":"user"}
----
@@ -214,6 +214,6 @@ Alternatively, you can also delete the explicit key. Enter the following into yo
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
We can now use the *x-auth-token* to make another request with the session we deleted and observe we are prompted for a authentication. For example, the following returns an HTTP 401:
We can now use the *X-Auth-Token* to make another request with the session we deleted and observe we are prompted for a authentication. For example, the following returns an HTTP 401:
$ curl -v http://localhost:8080/ -H "x-auth-token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"
$ curl -v http://localhost:8080/ -H "X-Auth-Token: 0dc1f6e1-c7f1-41ac-8ce2-32b6b3e57aa3"

View File

@@ -79,7 +79,7 @@ Add the following Spring Configuration:
[source,java]
----
include::{samples-dir}security/src/main/java/sample/Config.java[tags=class]
include::{samples-dir}javaconfig/security/src/main/java/sample/Config.java[tags=class]
----
<1> The `@EnableRedisHttpSession` annotation creates a Spring Bean with the name of `springSessionRepositoryFilter` that implements Filter.
@@ -100,7 +100,7 @@ Since our application is already loading Spring configuration using our `Securit
.src/main/java/sample/SecurityInitializer.java
[source,java]
----
include::{samples-dir}security/src/main/java/sample/SecurityInitializer.java[tags=class]
include::{samples-dir}javaconfig/security/src/main/java/sample/SecurityInitializer.java[tags=class]
----
Last we need to ensure that our Servlet Container (i.e. Tomcat) uses our `springSessionRepositoryFilter` for every request.
@@ -112,7 +112,7 @@ You can find an example below:
.src/main/java/sample/Initializer.java
[source,java]
----
include::{samples-dir}security/src/main/java/sample/Initializer.java[tags=class]
include::{samples-dir}javaconfig/security/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`.
@@ -170,4 +170,4 @@ Alternatively, you can also delete the explicit key. Enter the following into yo
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
Now visit the application at http://localhost:8080/ and observe that we are no longer authenticated.
Now visit the application at http://localhost:8080/ and observe that we are no longer authenticated.

View File

@@ -99,7 +99,7 @@ We can obtain the `HttpSessionManager` from the `HttpServletRequest` using the f
.src/main/java/sample/UserAccountsFilter.java
[source,java,indent=0]
----
include::{samples-dir}users/src/main/java/sample/UserAccountsFilter.java[tags=HttpSessionManager]
include::{samples-dir}javaconfig/users/src/main/java/sample/UserAccountsFilter.java[tags=HttpSessionManager]
----
We can now use it to create a URL to add another session.
@@ -107,7 +107,7 @@ We can now use it to create a URL to add another session.
.src/main/java/sample/UserAccountsFilter.java
[source,java,indent=0]
----
include::{samples-dir}users/src/main/java/sample/UserAccountsFilter.java[tags=addAccountUrl]
include::{samples-dir}javaconfig/users/src/main/java/sample/UserAccountsFilter.java[tags=addAccountUrl]
----
<1> We have an existing variable named `unauthenticatedAlias`.
@@ -148,7 +148,7 @@ For example, if we are currently using the session with the alias of *1*, then t
.src/main/webapp/index.jsp
[source,xml,indent=0]
----
include::{samples-dir}users/src/main/webapp/index.jsp[tags=link]
include::{samples-dir}javaconfig/users/src/main/webapp/index.jsp[tags=link]
----
will output a link of:

View File

@@ -80,7 +80,7 @@ Add the following Spring Configuration:
[source,xml]
----
include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/webapp/WEB-INF/spring/session-client.xml[tags=beans]
include::{samples-dir}xml/gemfire-clientserver/src/main/webapp/WEB-INF/spring/session-client.xml[tags=beans]
----
<1> Spring annotation configuration support is enabled with `<context:annotation-config/>` element so that any
@@ -92,7 +92,7 @@ bean to replace placeholders in the Spring XML configuration meta-data with the
at the designated host/port is running and listening for client connections, blocking client startup until
the server is available and ready.
<4> Next, we include a `Properties` bean to configure certain aspects of the GemFire client cache using
https://gemfire.docs.pivotal.io/docs-gemfire/latest/reference/topics/gemfire_properties.html[GemFire's System Properties].
https://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 application-specific System property, defaulting
to `warning` if unspecified.
<5> Then we create a instance of a GemFire `ClientCache` initialized with our `gemfireProperties`.
@@ -117,7 +117,7 @@ In this sample, we will use the following GemFire Server Java Configuration:
[source,xml]
----
include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/resources/META-INF/spring/session-server.xml[tags=beans]
include::{samples-dir}xml/gemfire-clientserver/src/main/resources/META-INF/spring/session-server.xml[tags=beans]
----
<1> First, we enable Spring annotation config support with the `<context:annotation-config>` element so that any
@@ -139,7 +139,7 @@ The GemFire Server configuration gets bootstrapped with the following:
[source,java]
----
include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/java/sample/Application.java[tags=class]
include::{samples-dir}xml/gemfire-clientserver/src/main/java/sample/Application.java[tags=class]
----
TIP: Instead of a simple Java class with a main method, you could also use _Spring Boot_.
@@ -163,8 +163,8 @@ We do this with the following configuration:
.src/main/webapp/WEB-INF/web.xml
[source,xml,indent=0]
----
include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/webapp/WEB-INF/web.xml[tags=context-param]
include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/webapp/WEB-INF/web.xml[tags=listeners]
include::{samples-dir}xml/gemfire-clientserver/src/main/webapp/WEB-INF/web.xml[tags=context-param]
include::{samples-dir}xml/gemfire-clientserver/src/main/webapp/WEB-INF/web.xml[tags=listeners]
----
The https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener]
@@ -178,7 +178,7 @@ The following snippet performs this last step for us:
.src/main/webapp/WEB-INF/web.xml
[source,xml,indent=0]
----
include::{samples-dir}httpsession-gemfire-clientserver-xml/src/main/webapp/WEB-INF/web.xml[tags=springSessionRepositoryFilter]
include::{samples-dir}xml/gemfire-clientserver/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]
@@ -225,7 +225,7 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
.src/main/java/sample/SessionServlet.java
[source,java]
----
include::{samples-dir}httpsession-gemfire-clientserver/src/main/java/sample/SessionServlet.java[tags=class]
include::{samples-dir}xml/gemfire-clientserver/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in GemFire.
@@ -234,7 +234,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/gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
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:

View File

@@ -81,7 +81,7 @@ Add the following Spring Configuration:
.src/main/webapp/WEB-INF/spring/session.xml
[source,xml,indent=0]
----
include::{samples-dir}httpsession-gemfire-p2p-xml/src/main/webapp/WEB-INF/spring/session.xml[tags=beans]
include::{samples-dir}xml/gemfire-p2p/src/main/webapp/WEB-INF/spring/session.xml[tags=beans]
----
<1> We use the combination of `<context:annotation-config/>` and `GemFireHttpSessionConfiguration` because Spring Session
@@ -114,8 +114,8 @@ We do this with the following configuration:
.src/main/webapp/WEB-INF/web.xml
[source,xml,indent=0]
----
include::{samples-dir}httpsession-gemfire-p2p-xml/src/main/webapp/WEB-INF/web.xml[tags=context-param]
include::{samples-dir}httpsession-gemfire-p2p-xml/src/main/webapp/WEB-INF/web.xml[tags=listeners]
include::{samples-dir}xml/gemfire-p2p/src/main/webapp/WEB-INF/web.xml[tags=context-param]
include::{samples-dir}xml/gemfire-p2p/src/main/webapp/WEB-INF/web.xml[tags=listeners]
----
The https://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#context-create[ContextLoaderListener]
@@ -129,7 +129,7 @@ The following snippet performs this last step for us:
.src/main/webapp/WEB-INF/web.xml
[source,xml,indent=0]
----
include::{samples-dir}httpsession-gemfire-p2p-xml/src/main/webapp/WEB-INF/web.xml[tags=springSessionRepositoryFilter]
include::{samples-dir}xml/gemfire-p2p/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]
@@ -167,7 +167,7 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
.src/main/java/sample/SessionServlet.java
[source,java]
----
include::{samples-dir}httpsession-gemfire-p2p-xml/src/main/java/sample/SessionServlet.java[tags=class]
include::{samples-dir}xml/gemfire-p2p/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in GemFire.
@@ -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/gemfire/getting_started/installation/install_intro.html[Installing Pivotal GemFire].
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:

View File

@@ -76,7 +76,7 @@ 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]
include::{samples-dir}xml/jdbc/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]).
@@ -101,8 +101,8 @@ 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]
include::{samples-dir}xml/jdbc/src/main/webapp/WEB-INF/web.xml[tags=context-param]
include::{samples-dir}xml/jdbc/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.
@@ -113,7 +113,7 @@ 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]
include::{samples-dir}xml/jdbc/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`.
@@ -150,7 +150,7 @@ 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]
include::{samples-dir}xml/jdbc/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in H2 database.

View File

@@ -81,7 +81,7 @@ Add the following Spring Configuration:
.src/main/webapp/WEB-INF/spring/session.xml
[source,xml,indent=0]
----
include::{samples-dir}httpsession-xml/src/main/webapp/WEB-INF/spring/session.xml[tags=beans]
include::{samples-dir}xml/redis/src/main/webapp/WEB-INF/spring/session.xml[tags=beans]
----
<1> We use the combination of `<context:annotation-config/>` and `RedisHttpSessionConfiguration` because Spring Session does not yet provide XML Namespace support (see https://github.com/spring-projects/spring-session/issues/104[gh-104]).
@@ -104,8 +104,8 @@ 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]
include::{samples-dir}xml/redis/src/main/webapp/WEB-INF/web.xml[tags=context-param]
include::{samples-dir}xml/redis/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.
@@ -116,7 +116,7 @@ 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]
include::{samples-dir}xml/redis/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`.
@@ -159,7 +159,7 @@ We interact with the standard `HttpSession` in the `SessionServlet` shown below:
.src/main/java/sample/SessionServlet.java
[source,java]
----
include::{samples-dir}httpsession-xml/src/main/java/sample/SessionServlet.java[tags=class]
include::{samples-dir}xml/redis/src/main/java/sample/SessionServlet.java[tags=class]
----
Instead of using Tomcat's `HttpSession`, we are actually persisting the values in Redis.
@@ -176,4 +176,4 @@ Alternatively, you can also delete the explicit key. Enter the following into yo
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.
Now visit the application at http://localhost:8080/ and observe that the attribute we added is no longer displayed.

View File

@@ -44,96 +44,116 @@ https://github.com/spring-projects/spring-session/milestone/19?closed=1[1.3.0.RE
If you are looking to get started with Spring Session, the best place to start is our Sample Applications.
.Sample Applications
.Sample Applications using Spring Boot
|===
| Source | Description | Guide
| {gh-samples-url}httpsession[HttpSession]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a Redis store.
| link:guides/httpsession.html[HttpSession Guide]
| {gh-samples-url}boot/redis[HttpSession with Redis]
| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis.
| link:guides/boot-redis.html[HttpSession with Redis Guide]
| {gh-samples-url}httpsession-xml[HttpSession XML]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a Redis store using XML based configuration.
| 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)]
| {gh-samples-url}boot/gemfire[HttpSession with GemFire]
| 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]
| link:guides/boot-gemfire.html[HttpSession with GemFire Guide]
| {gh-samples-url}httpsession-gemfire-clientserver-xml[HttpSession with GemFire (Client/Server) using XML]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a Client/Server topology configured with XML.
| link:guides/httpsession-gemfire-clientserver-xml.html[HttpSession GemFire Client/Server XML Guide]
| {gh-samples-url}boot/mongo[HttpSession with Mongo]
| Demonstrates how to use Spring Session to replace the `HttpSession` with Mongo.
| link:guides/boot-mongo.html[HttpSession with Mongo Guide]
| {gh-samples-url}httpsession-gemfire-p2p[HttpSession with GemFire (P2P)]
| {gh-samples-url}boot/jdbc[HttpSession with JDBC]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store.
| link:guides/boot-jdbc.html[HttpSession with JDBC Guide]
| {gh-samples-url}boot/findbyusername[Find by Username]
| Demonstrates how to use Spring Session to find sessions by username.
| link:guides/boot-findbyusername.html[Find by Username Guide]
| {gh-samples-url}boot/websocket[WebSockets]
| Demonstrates how to use Spring Session with WebSockets.
| link:guides/boot-websocket.html[WebSockets Guide]
| {gh-samples-url}boot/redis-json[HttpSession with Redis JSON serialization]
| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis using JSON serialization.
| TBD
|===
.Sample Applications using Spring Java based configuration
|===
| Source | Description | Guide
| {gh-samples-url}javaconfig/redis[HttpSession with Redis]
| Demonstrates how to use Spring Session to replace the `HttpSession` with Redis.
| link:guides/java-redis.html[HttpSession with Redis Guide]
| {gh-samples-url}javaconfig/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/java-gemfire-clientserver.html[HttpSession with GemFire (Client/Server) Guide]
| {gh-samples-url}javaconfig/gemfire-p2p[HttpSession with GemFire (P2P)]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a P2P topology.
| link:guides/httpsession-gemfire-p2p.html[HttpSession GemFire P2P Guide]
| link:guides/java-gemfire-p2p.html[HttpSession with GemFire (P2P) Guide]
| {gh-samples-url}httpsession-gemfire-p2p-xml[HttpSession with GemFire (P2P) using XML]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a P2P topology configured with XML.
| link:guides/httpsession-gemfire-p2p-xml.html[HttpSession GemFire P2P XML Guide]
| {gh-samples-url}javaconfig/jdbc[HttpSession with JDBC]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store.
| link:guides/java-jdbc.html[HttpSession with JDBC Guide]
| {gh-samples-url}custom-cookie[Custom Cookie]
| {gh-samples-url}javaconfig/hazelcast[HttpSession with Hazelcast]
| Demonstrates how to use Spring Session to replace the `HttpSession` with Hazelcast.
| link:guides/java-hazelcast.html[HttpSession with Hazelcast Guide]
| {gh-samples-url}javaconfig/custom-cookie[Custom Cookie]
| Demonstrates how to use Spring Session and customize the cookie.
| link:guides/custom-cookie.html[Custom Cookie Guide]
| link:guides/java-custom-cookie.html[Custom Cookie Guide]
| {gh-samples-url}boot[Spring Boot]
| Demonstrates how to use Spring Session with Spring Boot.
| link:guides/boot.html[Spring Boot Guide]
| {gh-samples-url}javaconfig/security[Spring Security]
| Demonstrates how to use Spring Session with an existing Spring Security application.
| link:guides/java-security.html[Spring Security Guide]
| {gh-samples-url}grails3[Grails 3]
| {gh-samples-url}javaconfig/rest[REST]
| Demonstrates how to use Spring Session in a REST application to support authenticating with a header.
| link:guides/java-rest.html[REST Guide]
| {gh-samples-url}javaconfig/users[Multiple Users]
| Demonstrates how to use Spring Session to manage multiple simultaneous browser sessions (i.e Google Accounts).
| link:guides/java-users.html[Multiple Users Guide]
|===
.Sample Applications using Spring XML based configuration
|===
| Source | Description | Guide
| {gh-samples-url}xml/redis[HttpSession with Redis]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a Redis store.
| link:guides/xml-redis.html[HttpSession with Redis Guide]
| {gh-samples-url}xml/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/xml-gemfire-clientserver.html[HttpSession with GemFire (Client/Server) Guide]
| {gh-samples-url}xml/gemfire-p2p[HttpSession with GemFire (P2P)]
| Demonstrates how to use Spring Session to replace the `HttpSession` with GemFire using a P2P topology.
| link:guides/xml-gemfire-p2p.html[HttpSession with GemFire (P2P) Guide]
| {gh-samples-url}xml/jdbc[HttpSession with JDBC]
| Demonstrates how to use Spring Session to replace the `HttpSession` with a relational database store.
| link:guides/xml-jdbc.html[HttpSession with JDBC Guide]
|===
.Misc sample Applications
|===
| Source | Description | Guide
| {gh-samples-url}misc/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]
| {gh-samples-url}rest[REST]
| Demonstrates how to use Spring Session in a REST application to support authenticating with a header.
| link:guides/rest.html[REST Guide]
| {gh-samples-url}findbyusername[Find by Username]
| Demonstrates how to use Spring Session to find sessions by username.
| link:guides/findbyusername.html[Find by Username]
| {gh-samples-url}users[Multiple Users]
| Demonstrates how to use Spring Session to manage multiple simultaneous browser sessions (i.e Google Accounts).
| link:guides/users.html[Manage Multiple Users Guide]
| {gh-samples-url}websocket[WebSocket]
| 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.
| {gh-samples-url}misc/hazelcast[Hazelcast]
| Demonstrates how to use Spring Session with Hazelcast in a Java EE application.
| TBD
[[samples-hazelcast-spring]]
| {gh-samples-url}hazelcast-spring[Hazelcast Spring]
| 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]]
@@ -168,7 +188,7 @@ This section describes how to use Redis to back `HttpSession` using Java based c
NOTE: The <<samples, HttpSession 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/httpsession.adoc[tags=config,leveloffset=+3]
include::guides/java-redis.adoc[tags=config,leveloffset=+3]
[[httpsession-redis-xml]]
==== Redis XML Based Configuration
@@ -178,7 +198,7 @@ This section describes how to use Redis to back `HttpSession` using XML based co
NOTE: The <<samples, HttpSession 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 XML Guide when integrating with your own application.
include::guides/httpsession-xml.adoc[tags=config,leveloffset=+3]
include::guides/xml-redis.adoc[tags=config,leveloffset=+3]
[[httpsession-gemfire]]
=== HttpSession with Pivotal GemFire
@@ -192,7 +212,7 @@ 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/latest/topologies_and_comm/multi_site_configuration/chapter_overview.html[WAN functionality].
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].
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].
@@ -223,7 +243,7 @@ Spring Session and GemFire to replace the HttpSession using Java configuration.
integration below, but you are encouraged to follow along with the detailed HttpSession with GemFire (Client-Server)
Guide when integrating with your own application.
include::guides/httpsession-gemfire-clientserver.adoc[tags=config,leveloffset=+3]
include::guides/java-gemfire-clientserver.adoc[tags=config,leveloffset=+3]
[[http-session-gemfire-clientserver-xml]]
===== GemFire Client-Server XML-based Configuration
@@ -235,7 +255,7 @@ integrate Spring Session and GemFire to replace the `HttpSession` using XML conf
for integration below, but you are encouraged to follow along with the detailed HttpSession with GemFire (Client-Server)
using XML Guide when integrating with your own application.
include::guides/httpsession-gemfire-clientserver-xml.adoc[tags=config,leveloffset=+3]
include::guides/xml-gemfire-clientserver.adoc[tags=config,leveloffset=+3]
[[httpsession-gemfire-p2p]]
==== GemFire Peer-To-Peer (P2P)
@@ -270,7 +290,7 @@ Spring Session and GemFire to replace the `HttpSession` using Java configuration
for integration below, but you are encouraged to follow along with the detailed HttpSession with GemFire (P2P) Guide
when integrating with your own application.
include::guides/httpsession-gemfire-p2p.adoc[tags=config,leveloffset=+3]
include::guides/java-gemfire-p2p.adoc[tags=config,leveloffset=+3]
[[httpsession-gemfire-p2p-xml]]
===== GemFire Peer-To-Peer (P2P) XML-based Configuration
@@ -282,7 +302,7 @@ Spring Session and GemFire to replace the `HttpSession` using XML configuration.
integration below, but you are encouraged to follow along with the detailed HttpSession with GemFire (P2P) using XML
Guide when integrating with your own application.
include::guides/httpsession-gemfire-p2p-xml.adoc[tags=config,leveloffset=+3]
include::guides/xml-gemfire-p2p.adoc[tags=config,leveloffset=+3]
[[httpsession-jdbc]]
=== HttpSession with JDBC
@@ -302,7 +322,7 @@ This section describes how to use a relational database to back `HttpSession` us
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]
include::guides/java-jdbc.adoc[tags=config,leveloffset=+3]
[[httpsession-jdbc-xml]]
==== JDBC XML Based Configuration
@@ -312,7 +332,7 @@ This section describes how to use a relational database to back `HttpSession` us
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]
include::guides/xml-jdbc.adoc[tags=config,leveloffset=+3]
[[httpsession-jdbc-boot]]
==== JDBC Spring Boot Based Configuration
@@ -322,7 +342,7 @@ This section describes how to use a relational database to back `HttpSession` wh
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]
include::guides/boot-jdbc.adoc[tags=config,leveloffset=+3]
[[httpsession-mongo]]
=== HttpSession with Mongo
@@ -334,7 +354,7 @@ This section describes how to use Mongo to back `HttpSession` using Java based c
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]
include::guides/boot-mongo.adoc[tags=config,leveloffset=+3]
==== Session serialization mechanisms
@@ -385,7 +405,7 @@ This section describes how to use Hazelcast to back `HttpSession` using Java bas
NOTE: The <<samples, Hazelcast Spring 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 Hazelcast Spring Guide when integrating with your own application.
include::guides/hazelcast-spring.adoc[tags=config,leveloffset=+2]
include::guides/java-hazelcast.adoc[tags=config,leveloffset=+2]
[[httpsession-how]]
=== How HttpSession Integration Works
@@ -452,7 +472,7 @@ This provides the ability to support authenticating with multiple users in the s
NOTE: The <<samples,Manage Multiple Users Guide>> provides a complete working example of managing multiple users in the same browser instance.
You can follow the basic steps for integration below, but you are encouraged to follow along with the detailed Manage Multiple Users Guide when integrating with your own application.
include::guides/users.adoc[tags=how-does-it-work,leveloffset=+1]
include::guides/java-users.adoc[tags=how-does-it-work,leveloffset=+1]
[[httpsession-rest]]
=== HttpSession & RESTful APIs
@@ -463,7 +483,7 @@ Spring Session can work with RESTful APIs by allowing the session to be provided
NOTE: The <<samples, REST Sample>> provides a working sample on how to use Spring Session in a REST application to support authenticating with a header.
You can follow the basic steps for integration below, but you are encouraged to follow along with the detailed REST Guide when integrating with your own application.
include::guides/rest.adoc[tags=config,leveloffset=+2]
include::guides/java-rest.adoc[tags=config,leveloffset=+2]
[[httpsession-httpsessionlistener]]
=== HttpSessionListener
@@ -496,7 +516,7 @@ include::{docs-test-resources-dir}docs/http/HttpSessionListenerXmlTests-context.
Spring Session provides transparent integration with Spring's WebSocket support.
include::guides/websocket.adoc[tags=disclaimer,leveloffset=+1]
include::guides/boot-websocket.adoc[tags=disclaimer,leveloffset=+1]
[[websocket-why]]
=== Why Spring Session & WebSockets?
@@ -522,7 +542,7 @@ You can follow the basic steps for integration below, but you are encouraged to
Before using WebSocket integration, you should be sure that you have <<httpsession>> working first.
include::guides/websocket.adoc[tags=config,leveloffset=+2]
include::guides/boot-websocket.adoc[tags=config,leveloffset=+2]
[[spring-security]]
== Spring Security Integration
@@ -829,12 +849,12 @@ EXPIRE spring:session:sessions:expires:33fdd1b6-b496-4b33-9f7d-df96679d32fe 1800
When a session expires key is deleted or expires, the keyspace notification triggers a lookup of the actual session and a SessionDestroyedEvent is fired.
One problem with relying on Redis expiration exclusively is that Redis makes no guarantee of when the expired event will be fired if the key has not been accessed.
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.
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 the key.
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.
For this reason, each session expiration is also tracked to the nearest minute.
This allows a background task to access the potentially expired sessions to ensure that Redis expired events are fired in a more deterministic fashion.
@@ -846,7 +866,7 @@ EXPIRE spring:session:expirations1439245080000 2100
----
The background task will then use these mappings to explicitly request each key.
By accessing the key, rather than deleting it, we ensure that Redis deletes the key for us only if the TTL is expired.
By accessing they key, rather than deleting it, we ensure that Redis deletes the key for us only if the TTL is expired.
[NOTE]
====
@@ -1143,16 +1163,6 @@ can be added to an `@Configuration` class. This extends the functionality provid
You must provide a single `HazelcastInstance` bean for the configuration to work.
Complete configuration example can be found in the <<samples>>
[[api-enablehazelcasthttpsession-storage]]
==== Storage Details
Sessions will be stored in a distributed `IMap` in Hazelcast using a <<api-mapsessionrepository,MapSessionRepository>>.
The `IMap` interface methods will be used to `get()` and `put()` Sessions.
Additionally, `values()` method is used to support `FindByIndexNameSessionRepository#findByIndexNameAndIndexValue` operation, together with appropriate `ValueExtractor` that needs to be registered with Hazelcast. Refer to <<samples, Hazelcast Spring Sample>> for more details on this configuration.
The expiration of a session in the `IMap` is handled by Hazelcast's support for setting the time to live on an entry when it is `put()` into the `IMap`. Entries (sessions) that have been idle longer than the time to live will be automatically removed from the `IMap`.
You shouldn't need to configure any settings such as `max-idle-seconds` or `time-to-live-seconds` for the `IMap` within the Hazelcast configuration.
[[api-enablehazelcasthttpsession-customize]]
==== Basic Customization
You can use the following attributes on `@EnableHazelcastHttpSession` to customize the configuration:
@@ -1163,7 +1173,22 @@ You can use the following attributes on `@EnableHazelcastHttpSession` to customi
[[api-enablehazelcasthttpsession-events]]
==== Session Events
Using a `MapListener` to respond to entries being added, evicted, and removed from the distributed `Map`, these events will trigger
publishing SessionCreatedEvent, SessionExpiredEvent, and SessionDeletedEvent events respectively using the `ApplicationEventPublisher`.
publishing `SessionCreatedEvent`, `SessionExpiredEvent`, and `SessionDeletedEvent` events respectively using the `ApplicationEventPublisher`.
[[api-enablehazelcasthttpsession-storage]]
==== Storage Details
Sessions will be stored in a distributed `IMap` in Hazelcast.
The `IMap` interface methods will be used to `get()` and `put()` Sessions.
Additionally, `values()` method is used to support `FindByIndexNameSessionRepository#findByIndexNameAndIndexValue` operation, together with appropriate `ValueExtractor` that needs to be registered with Hazelcast. Refer to <<samples, Hazelcast Spring Sample>> for more details on this configuration.
The expiration of a session in the `IMap` is handled by Hazelcast's support for setting the time to live on an entry when it is `put()` into the `IMap`. Entries (sessions) that have been idle longer than the time to live will be automatically removed from the `IMap`.
You shouldn't need to configure any settings such as `max-idle-seconds` or `time-to-live-seconds` for the `IMap` within the Hazelcast configuration.
Note that if you use Hazelcast's `MapStore` to persist your sessions `IMap` there are some limitations when reloading the sessions from `MapStore`:
* reload triggers `EntryAddedListener` which results in `SessionCreatedEvent` being re-published
* reload uses default TTL for a given `IMap` which results in sessions losing their original TTL
[[community]]
== Spring Session Community
@@ -1199,17 +1224,8 @@ Spring Session is Open Source software released under the https://www.apache.org
[[community-extensions]]
=== Community Extensions
|===
| Name | Location
| Spring Session OrientDB
| https://github.com/maseev/spring-session-orientdb
| Spring Session Infinispan
| https://infinispan.org/docs/dev/user_guide/user_guide.html#externalizing_session_using_spring_session
|===
https://github.com/maseev/spring-session-orientdb[Spring Session OrientDB]
https://infinispan.org/docs/dev/user_guide/user_guide.html#externalizing_session_using_spring_session[Spring Session Infinispan]
[[minimum-requirements]]
== Minimum Requirements

View File

@@ -71,8 +71,6 @@ public class AbstractGemFireIntegrationTests {
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;
@@ -82,7 +80,7 @@ public class AbstractGemFireIntegrationTests {
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");
.getProperty("spring.session.data.gemfire.log-file", "gemfire-server.log");
@Autowired
protected Cache gemfireCache;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2018 the original author or authors.
* 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.
@@ -22,6 +22,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.authentication.RememberMeServices;
import org.springframework.session.MapSessionRepository;
import org.springframework.session.config.annotation.web.http.EnableSpringHttpSession;
import org.springframework.session.security.web.authentication.SpringSessionRememberMeServices;
@@ -51,7 +52,7 @@ public class RememberMeSecurityConfiguration extends WebSecurityConfigurerAdapte
// tag::rememberme-bean[]
@Bean
public SpringSessionRememberMeServices rememberMeServices() {
RememberMeServices rememberMeServices() {
SpringSessionRememberMeServices rememberMeServices =
new SpringSessionRememberMeServices();
// optionally customize

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2017 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.
@@ -21,6 +21,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.session.ExpiringSession;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.security.SpringSessionBackedSessionRegistry;
@@ -32,21 +33,23 @@ import org.springframework.session.security.SpringSessionBackedSessionRegistry;
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private FindByIndexNameSessionRepository sessionRepository;
private FindByIndexNameSessionRepository<ExpiringSession> sessionRepository;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
// other config goes here...
.sessionManagement()
.maximumSessions(2)
.sessionRegistry(sessionRegistry());
// @formatter:on
}
@Bean
@SuppressWarnings("unchecked")
public SpringSessionBackedSessionRegistry sessionRegistry() {
return new SpringSessionBackedSessionRegistry(this.sessionRepository);
SpringSessionBackedSessionRegistry sessionRegistry() {
return new SpringSessionBackedSessionRegistry<ExpiringSession>(
this.sessionRepository);
}
}
// end::class[]

View File

@@ -59,7 +59,7 @@ cleanup_profile=_Spring Boot Cleanup Conventions
cleanup_settings_version=2
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
formatter_profile=Spring Session Java Conventions
formatter_profile=_Spring Boot Java Conventions
formatter_settings_version=12
org.eclipse.jdt.ui.exception.name=e
org.eclipse.jdt.ui.gettersetter.use.is=true

View File

@@ -1,31 +1,30 @@
assertjVersion=2.6.0
bootstrapVersion=2.3.2
commonsPoolVersion=2.4.2
jacksonVersion=2.8.8
jspApiVersion=2.0
servletApiVersion=3.0.1
jstlelVersion=1.2.5
version=1.3.6.BUILD-SNAPSHOT
springDataRedisVersion=1.7.11.RELEASE
html5ShivVersion=3.7.3
commonsLoggingVersion=1.2
junitVersion=4.12
springDataRedisSpring3Version=1.7.1.RELEASE
lettuceVersion=3.5.0.Final
commonsPoolVersion=2.4.2
gebVersion=0.13.1
mockitoVersion=1.10.19
hazelcastVersion=3.6.8
seleniumVersion=2.52.0
springDataGeodeVersion=1.0.0.INCUBATING-RELEASE
springSecurityVersion=4.2.11.RELEASE
springVersion=4.3.19.RELEASE
httpClientVersion=4.5.3
groovyVersion=2.4.11
h2Version=1.4.195
jedisVersion=2.8.2
springDataMongoVersion=1.9.11.RELEASE
hazelcastVersion=3.7.7
httpClientVersion=4.5.3
html5ShivVersion=3.7.3
jacksonVersion=2.8.8
jedisVersion=2.9.0
jspApiVersion=2.0
jstlVersion=1.2.1
jstlelVersion=1.2.5
junitVersion=4.12
lettuceVersion=4.3.0.Final
mockitoVersion=1.10.19
seleniumVersion=2.52.0
servletApiVersion=3.0.1
springVersion=4.3.9.RELEASE
springDataGemFireVersion=1.9.4.RELEASE
springDataGeodeVersion=1.0.0.INCUBATING-RELEASE
springDataMongoVersion=1.10.4.RELEASE
springDataRedisVersion=1.8.4.RELEASE
springSecurityVersion=4.2.3.RELEASE
springShellVersion=1.1.0.RELEASE
springDataGemFireVersion=1.8.11.RELEASE
assertjVersion=2.5.0
spockVersion=1.0-groovy-2.4
webjarsTaglibVersion=0.3
jstlVersion=1.2.1
groovyVersion=2.4.11
version=1.4.0.BUILD-SNAPSHOT

View File

@@ -5,6 +5,12 @@ import org.gradle.plugins.ide.eclipse.model.SourceFolder
apply plugin: "propdeps-eclipse"
apply plugin: "propdeps-idea"
eclipse {
jdt {
javaRuntimeName = "J2SE-1.5"
}
}
eclipse.project.buildCommand "net.sf.eclipsecs.core.CheckstyleBuilder"
eclipse.project.natures "net.sf.eclipsecs.core.CheckstyleNature"

View File

@@ -14,7 +14,7 @@ group = 'org.springframework.session'
sourceCompatibility = 1.5
targetCompatibility = 1.5
ext.springIoVersion = project.hasProperty('platformVersion') ? platformVersion : 'Brussels-BUILD-SNAPSHOT'
ext.springIoVersion = project.hasProperty('platformVersion') ? platformVersion : 'Brussels-SR3'
ext.spockDependencies = [
dependencies.create("org.spockframework:spock-core:$spockVersion") {
@@ -28,9 +28,14 @@ ext.gebDependencies = spockDependencies + [
"org.codehaus.groovy:groovy:$groovyVersion"
]
ext.seleniumDependencies = [
"org.seleniumhq.selenium:selenium-htmlunit-driver:$seleniumVersion",
"org.seleniumhq.selenium:selenium-firefox-driver:$seleniumVersion"
]
ext.jstlDependencies = [
"javax.servlet.jsp.jstl:javax.servlet.jsp.jstl-api:$jstlVersion",
"org.apache.taglibs:taglibs-standard-jstlel:1.2.1"
"org.apache.taglibs:taglibs-standard-jstlel:$jstlelVersion"
]
repositories {
@@ -78,7 +83,7 @@ task integrationTest(type: Test, dependsOn: jar) {
check.dependsOn integrationTest
checkstyle {
configFile = rootProject.file('etc/checkstyle/checkstyle.xml')
configFile = rootProject.file('config/checkstyle/checkstyle.xml')
configProperties.configDir = configFile.parentFile
toolVersion = '6.16.1'
}

View File

@@ -1,27 +0,0 @@
configurations {
spring3TestRuntime.extendsFrom testRuntime
}
configurations.spring3TestRuntime {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'org.springframework'
&& details.requested.name != 'spring-websocket'
&& details.requested.name != 'spring-messaging') {
details.useVersion '3.2.14.RELEASE'
}
if (details.requested.name == 'spring-data-redis') {
details.useVersion springDataRedisSpring3Version
}
}
}
task spring3Test(type: Test) {
jvmArgs = ['-ea', '-Xmx500m', '-XX:MaxPermSize=128M']
classpath = sourceSets.test.output + sourceSets.main.output + configurations.spring3TestRuntime
exclude "org/springframework/session/web/socket/**"
reports {
html.destination = project.file("$buildDir/spring3-test-results/")
junitXml.destination = project.file("$buildDir/reports/spring3-tests/")
}
}
check.dependsOn spring3Test

View File

@@ -45,9 +45,7 @@ task integrationTomcatStop(type: com.bmuschko.gradle.tomcat.tasks.TomcatStop) {
integrationTest {
dependsOn integrationTomcatRun
doFirst {
def host = 'localhost:' + integrationTomcatRun.httpPort
systemProperties['geb.build.baseUrl'] = 'http://'+host+'/' + integrationTomcatRun.contextPath
systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
systemProperties['tomcat.port'] = integrationTomcatRun.httpPort
}
finalizedBy integrationTomcatStop
}

Binary file not shown.

View File

@@ -1,6 +1,6 @@
#Mon Jan 29 18:35:20 CET 2018
#Wed Jan 11 10:54:44 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.5.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-bin.zip

19
gradlew vendored
View File

@@ -1,4 +1,4 @@
#!/usr/bin/env sh
#!/usr/bin/env bash
##############################################################################
##
@@ -154,19 +154,16 @@ if $cygwin ; then
esac
fi
# Escape application args
save ( ) {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
if [[ "$(uname)" == "Darwin" ]] && [[ "$HOME" == "$PWD" ]]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@@ -1,6 +1,7 @@
buildscript {
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
@@ -14,8 +15,6 @@ apply from: SAMPLE_GRADLE
group = 'samples'
ext['spring-security.version'] = springSecurityVersion
dependencies {
compile project(':spring-session'),
"org.springframework.boot:spring-boot-starter-data-redis",
@@ -33,8 +32,7 @@ dependencies {
testCompile "org.springframework.boot:spring-boot-starter-test",
"org.assertj:assertj-core:$assertjVersion"
integrationTestCompile gebDependencies,
"org.spockframework:spock-spring:$spockVersion"
integrationTestCompile seleniumDependencies
}
@@ -42,9 +40,6 @@ integrationTest {
doFirst {
def port = reservePort()
def host = 'localhost:' + port
systemProperties['geb.build.baseUrl'] = 'http://'+host+'/'
systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
systemProperties['server.port'] = port
systemProperties['management.port'] = 0

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2014-2017 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 sample;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
import sample.pages.HomePage;
import sample.pages.LoginPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
/**
* @author Eddú Meléndez
* @author Rob Winch
*/
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
public class FindByUsernameTests {
@Autowired
private MockMvc mockMvc;
private WebDriver driver;
@Before
public void setup() {
this.driver = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(this.mockMvc).build();
}
@After
public void tearDown() {
this.driver.quit();
}
@Test
public void home() {
LoginPage login = HomePage.go(this.driver);
login.assertAt();
}
@Test
public void login() {
LoginPage login = HomePage.go(this.driver);
HomePage home = login.form().login(HomePage.class);
home.assertAt();
home.containCookie("SESSION");
home.doesNotContainCookie("JSESSIONID");
home.terminateButtonDisabled();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2017 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.
@@ -14,20 +14,28 @@
* limitations under the License.
*/
package sample.pages
package sample.pages;
import geb.*
import org.openqa.selenium.WebDriver;
/**
* The home page
*
* @author Rob Winch
* @author Eddú Meléndez
*/
class HomePage extends Page {
static url = ''
static at = { assert driver.title == 'Spring Session Sample - Secured Content'; true}
static content = {
username { $('#un').text() }
logout(to:LoginPage) { $('input[type=submit]').click() }
public class BasePage {
private WebDriver driver;
public BasePage(WebDriver driver) {
this.driver = driver;
}
public WebDriver getDriver() {
return this.driver;
}
public static void get(WebDriver driver, String get) {
String baseUrl = "http://localhost";
driver.get(baseUrl + get);
}
}

View File

@@ -0,0 +1,78 @@
/*
* Copyright 2014-2017 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 sample.pages;
import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Eddú Meléndez
* @author Rob Winch
*/
public class HomePage extends BasePage {
@FindBy(css = "input[type=\"submit\"]")
WebElement logout;
public HomePage(WebDriver driver) {
super(driver);
}
public void assertAt() {
assertThat(getDriver().getTitle())
.isEqualTo("Spring Session Sample - Secured Content");
}
public void containCookie(String cookieName) {
Set<Cookie> cookies = getDriver().manage().getCookies();
assertThat(cookies).extracting("name").contains(cookieName);
}
public void doesNotContainCookie(String cookieName) {
Set<Cookie> cookies = getDriver().manage().getCookies();
assertThat(cookies).extracting("name").doesNotContain(cookieName);
}
public void terminateButtonDisabled() {
Set<Cookie> cookies = getDriver().manage().getCookies();
String cookieValue = null;
for (Cookie cookie : cookies) {
if ("SESSION".equals(cookie.getName())) {
cookieValue = cookie.getValue();
}
}
WebElement element = getDriver().findElement(By.id("terminate-" + cookieValue));
assertThat(element.isEnabled()).isFalse();
}
public HomePage logout() {
this.logout.click();
return PageFactory.initElements(getDriver(), HomePage.class);
}
public static LoginPage go(WebDriver driver) {
get(driver, "/");
return PageFactory.initElements(driver, LoginPage.class);
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2014-2017 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 sample.pages;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.pagefactory.DefaultElementLocatorFactory;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Eddú Meléndez
* @author Rob Winch
*/
public class LoginPage extends BasePage {
public LoginPage(WebDriver driver) {
super(driver);
}
public void assertAt() {
assertThat(getDriver().getTitle()).isEqualTo("Spring Session Sample - Log In");
}
public Form form() {
return new Form(getDriver());
}
public class Form {
@FindBy(name = "username")
private WebElement username;
@FindBy(name = "password")
private WebElement password;
@FindBy(tagName = "button")
private WebElement button;
public Form(SearchContext context) {
PageFactory.initElements(new DefaultElementLocatorFactory(context), this);
}
public <T> T login(Class<T> page) {
this.username.sendKeys("user");
this.password.sendKeys("password");
this.button.click();
return PageFactory.initElements(getDriver(), page);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2017 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.
@@ -17,16 +17,12 @@
package sample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Rob Winch
*/
@Configuration
@ComponentScan
@EnableAutoConfiguration
@SpringBootApplication
public class FindByUsernameApplication {
public static void main(String[] args) {

View File

Before

Width:  |  Height:  |  Size: 30 MiB

After

Width:  |  Height:  |  Size: 30 MiB

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,6 +1,7 @@
buildscript {
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion"
@@ -12,8 +13,6 @@ apply plugin: "application"
apply plugin: 'org.springframework.boot'
apply from: SAMPLE_GRADLE
ext['spring-security.version'] = springSecurityVersion
dependencies {
compile project(':spring-session-data-gemfire'),
"org.springframework.boot:spring-boot-starter-thymeleaf",
@@ -21,14 +20,13 @@ dependencies {
"org.webjars:bootstrap:$bootstrapVersion",
"org.webjars:webjars-locator"
runtime "org.springframework.shell:spring-shell:$springShellVersion"
runtime "org.springframework.shell:spring-shell:1.0.0.RELEASE"
testCompile "org.springframework.boot:spring-boot-starter-test"
integrationTestCompile gebDependencies,
"org.spockframework:spock-spring:$spockVersion"
integrationTestCompile seleniumDependencies
integrationTestRuntime "org.springframework.shell:spring-shell:$springShellVersion"
integrationTestRuntime "org.springframework.shell:spring-shell:1.0.0.RELEASE"
}
run {
@@ -43,23 +41,34 @@ springBoot {
task runGemFireServer() {
doLast {
println 'STARTING GEMFIRE SERVER...'
ext.port = reservePort()
println "Starting GemFire Server on port [$port] ..."
def out = new StringBuilder()
def err = new StringBuilder()
String classpath = sourceSets.main.runtimeClasspath.collect { it }.join(File.pathSeparator)
String[] commandLine = ['java', '-server', '-ea', '-classpath', classpath,
"-Dgemfire.cache.server.port=$port",
"-Dgemfire.log-level=" + System.getProperty('gemfire.log.level', 'warning'),
'sample.server.GemFireServer']
String[] commandLine = [
'java', '-server', '-ea', '-classpath', classpath,
//"-Dgemfire.log-file=gemfire-server.log",
//"-Dgemfire.log-level=config",
"-Dspring-session-data-gemfire.cache.server.port=$port",
"-Dspring-session-data-gemfire.log.level="
+ System.getProperty('spring-session-data-gemfire.log.level', 'warning'),
'sample.server.GemFireServer'
]
//println commandLine
ext.process = commandLine.execute()
process.in.close()
process.out.close()
process.err.close()
//ext.process = new ProcessBuilder().command(commandLine).redirectErrorStream(true).start();
ext.process.consumeProcessOutput(out, err)
//println 'OUT: ' + out
//println 'ERR: ' + err
}
}
@@ -68,15 +77,15 @@ integrationTest {
dependsOn runGemFireServer
doFirst {
def port = reservePort()
def host = 'localhost:' + port
systemProperties['server.port'] = port
systemProperties['management.port'] = 0
systemProperties['geb.build.baseUrl'] = 'http://'+host+'/'
systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
systemProperties['gemfire.cache.server.port'] = runGemFireServer.port
systemProperties['server.port'] = port
//systemProperties['gemfire.log-file'] = "gemfire-client.log"
//systemProperties['gemfire.log-level'] = "config"
systemProperties['spring-session-data-gemfire.cache.server.port'] = runGemFireServer.port
systemProperties['spring-session-data-gemfire.log.level'] = System.getProperty("spring-session-data-gemfire.log.level", "warning")
}
doLast {
println 'STOPPING GEMFIRE SERVER...'
println 'Stopping GemFire Server...'
runGemFireServer.process?.destroyForcibly()
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2014-2017 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 sample;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
import sample.client.Application;
import sample.pages.HomePage;
import sample.pages.HomePage.Attribute;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Eddú Meléndez
* @author Rob Winch
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.MOCK)
@AutoConfigureMockMvc
public class AttributeTests {
@Autowired
private MockMvc mockMvc;
private WebDriver driver;
@Before
public void setup() {
this.driver = MockMvcHtmlUnitDriverBuilder
.mockMvcSetup(this.mockMvc)
.build();
}
@After
public void tearDown() {
this.driver.quit();
}
@Test
public void home() {
HomePage home = HomePage.go(this.driver);
home.assertAt();
}
@Test
public void noAttributes() {
HomePage home = HomePage.go(this.driver);
assertThat(home.attributes()).isEmpty();
}
@Test
public void createAttribute() {
HomePage home = HomePage.go(this.driver);
// @formatter:off
home = home.form()
.attributeName("a")
.attributeValue("b")
.submit(HomePage.class);
// @formatter:on
List<Attribute> attributes = home.attributes();
assertThat(attributes).hasSize(2);
assertThat(attributes.get(0).getAttributeName()).isEqualTo("requestCount");
assertThat(attributes.get(0).getAttributeValue()).isEqualTo("1");
assertThat(attributes.get(1).getAttributeName()).isEqualTo("a");
assertThat(attributes.get(1).getAttributeValue()).isEqualTo("b");
}
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright 2014-2017 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 sample.pages;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.pagefactory.DefaultElementLocatorFactory;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Eddú Meléndez
* @author Rob Winch
*/
public class HomePage {
private WebDriver driver;
@FindBy(css = "form")
WebElement form;
@FindBy(css = "table tbody tr")
List<WebElement> trs;
List<Attribute> attributes;
public HomePage(WebDriver driver) {
this.driver = driver;
this.attributes = new ArrayList<Attribute>();
}
private static void get(WebDriver driver, String get) {
String baseUrl = "http://localhost:" + System.getProperty("tomcat.port", "8080");
driver.get(baseUrl + get);
}
public static HomePage go(WebDriver driver) {
get(driver, "/");
return PageFactory.initElements(driver, HomePage.class);
}
public void assertAt() {
assertThat(this.driver.getTitle()).isEqualTo("Session Attributes");
}
public List<Attribute> attributes() {
List<Attribute> rows = new ArrayList<Attribute>();
for (WebElement tr : this.trs) {
rows.add(new Attribute(tr));
}
this.attributes.addAll(rows);
return this.attributes;
}
public Form form() {
return new Form(this.form);
}
public class Form {
@FindBy(name = "attributeName")
WebElement attributeName;
@FindBy(name = "attributeValue")
WebElement attributeValue;
@FindBy(css = "input[type=\"submit\"]")
WebElement submit;
public Form(SearchContext context) {
PageFactory.initElements(new DefaultElementLocatorFactory(context), this);
}
public Form attributeName(String text) {
this.attributeName.sendKeys(text);
return this;
}
public Form attributeValue(String text) {
this.attributeValue.sendKeys(text);
return this;
}
public <T> T submit(Class<T> page) {
this.submit.click();
return PageFactory.initElements(HomePage.this.driver, page);
}
}
public static class Attribute {
@FindBy(xpath = ".//td[1]")
WebElement attributeName;
@FindBy(xpath = ".//td[2]")
WebElement attributeValue;
public Attribute(SearchContext context) {
PageFactory.initElements(new DefaultElementLocatorFactory(context), this);
}
/**
* @return the attributeName
*/
public String getAttributeName() {
return this.attributeName.getText();
}
/**
* @return the attributeValue
*/
public String getAttributeValue() {
return this.attributeValue.getText();
}
}
}

View File

@@ -24,10 +24,16 @@ import java.util.Map;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.http.HttpSession;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolManager;
import com.gemstone.gemfire.cache.client.internal.PoolImpl;
import com.gemstone.gemfire.management.membership.ClientMembership;
import com.gemstone.gemfire.management.membership.ClientMembershipEvent;
import com.gemstone.gemfire.management.membership.ClientMembershipListenerAdapter;
@@ -40,10 +46,11 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.data.gemfire.client.ClientCacheFactoryBean;
import org.springframework.data.gemfire.client.PoolFactoryBean;
import org.springframework.data.gemfire.config.xml.GemfireConstants;
import org.springframework.data.gemfire.support.ConnectionEndpoint;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.Assert;
@@ -64,19 +71,21 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
* @see org.springframework.stereotype.Controller
* @see com.gemstone.gemfire.cache.client.ClientCache
* @see com.gemstone.gemfire.cache.client.Pool
* @since 1.2.1
*/
// tag::class[]
@SpringBootApplication
@EnableGemFireHttpSession // <1>
@EnableGemFireHttpSession(poolName = "DEFAULT")// <1>
@Controller
public class Application {
static final long DEFAULT_WAIT_DURATION = TimeUnit.SECONDS.toMillis(60);
static final long DEFAULT_TIMEOUT = TimeUnit.SECONDS.toMillis(60);
static final CountDownLatch latch = new CountDownLatch(1);
static final CountDownLatch LATCH = new CountDownLatch(1);
static final String DEFAULT_GEMFIRE_LOG_LEVEL = "warning";
static final String GEMFIRE_DEFAULT_POOL_NAME = "DEFAULT";
static final String INDEX_TEMPLATE_VIEW_NAME = "index";
static final String PING_RESPONSE = "PONG";
static final String REQUEST_COUNT_ATTRIBUTE_NAME = "requestCount";
@@ -94,83 +103,76 @@ public class Application {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
//gemfireProperties.setProperty("log-file", "gemfire-client.log");
gemfireProperties.setProperty("log-level", logLevel());
return gemfireProperties;
}
String applicationName() {
return "samples:httpsession-gemfire-boot:"
.concat(getClass().getSimpleName());
return "spring-session-data-gemfire-boot-sample.".concat(getClass().getSimpleName());
}
String logLevel() {
return System.getProperty("gemfire.log-level", DEFAULT_GEMFIRE_LOG_LEVEL);
return System.getProperty("spring-session-data-gemfire.log.level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
ClientCacheFactoryBean gemfireCache() { // <3>
ClientCacheFactoryBean gemfireCache(
@Value("${spring-session-data-gemfire.cache.server.host:localhost}") String host,
@Value("${spring-session-data-gemfire.cache.server.port:12480}") int port) { // <3>
ClientCacheFactoryBean gemfireCache = new ClientCacheFactoryBean();
gemfireCache.setClose(true);
gemfireCache.setProperties(gemfireProperties());
// GemFire Pool settings <4>
gemfireCache.setKeepAlive(false);
gemfireCache.setPingInterval(TimeUnit.SECONDS.toMillis(5));
gemfireCache.setReadTimeout(intValue(TimeUnit.SECONDS.toMillis(15)));
gemfireCache.setRetryAttempts(1);
gemfireCache.setSubscriptionEnabled(true);
gemfireCache.setThreadLocalConnections(false);
gemfireCache.setServers(Collections.singletonList(newConnectionEndpoint(host, port)));
registerClientMembershipListener(); // <5>
return gemfireCache;
}
@Bean
PoolFactoryBean gemfirePool(
@Value("${gemfire.cache.server.host:localhost}") String host,
@Value("${gemfire.cache.server.port:12480}") int port) { // <4>
PoolFactoryBean gemfirePool = new PoolFactoryBean();
gemfirePool.setKeepAlive(false);
gemfirePool.setPingInterval(TimeUnit.SECONDS.toMillis(5));
gemfirePool.setReadTimeout(Long.valueOf(TimeUnit.SECONDS.toMillis(15)).intValue());
gemfirePool.setRetryAttempts(1);
gemfirePool.setSubscriptionEnabled(true);
gemfirePool.setThreadLocalConnections(false);
gemfirePool.setServers(Collections.singleton(newConnectionEndpoint(host, port)));
return gemfirePool;
int intValue(Number number) {
return number.intValue();
}
ConnectionEndpoint newConnectionEndpoint(String host, int port) {
return new ConnectionEndpoint(host, port);
}
void registerClientMembershipListener() {
ClientMembership.registerClientMembershipListener(new ClientMembershipListenerAdapter() {
@Override
public void memberJoined(ClientMembershipEvent event) {
LATCH.countDown();
}
});
}
@Bean
BeanPostProcessor gemfireCacheServerReadyBeanPostProcessor(
@Value("${gemfire.cache.server.host:localhost}") final String host,
@Value("${gemfire.cache.server.port:12480}") final int port) { // <5>
BeanPostProcessor gemfireClientServerReadyBeanPostProcessor(
@Value("${spring-session-data-gemfire.cache.server.host:localhost}") final String host,
@Value("${spring-session-data-gemfire.cache.server.port:12480}") final int port) { // <5>
return new BeanPostProcessor() {
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
private final AtomicBoolean checkGemFireServerIsRunning = new AtomicBoolean(true);
private final AtomicReference<Pool> defaultPool = new AtomicReference<Pool>(null);
if ("gemfirePool".equals(beanName)) {
ClientMembership.registerClientMembershipListener(
new ClientMembershipListenerAdapter() {
@Override
public void memberJoined(ClientMembershipEvent event) {
latch.countDown();
}
});
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (bean instanceof Pool && "gemfirePool".equals(beanName)) {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (shouldCheckWhetherGemFireServerIsRunning(bean, beanName)) {
try {
Assert.state(latch.await(DEFAULT_WAIT_DURATION, TimeUnit.MILLISECONDS),
String.format("GemFire Cache Server failed to start on host [%1$s] and port [%2$d]",
host, port));
validateCacheClientNotified();
validateCacheClientSubscriptionQueueConnectionEstablished();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt();
@@ -179,6 +181,73 @@ public class Application {
return bean;
}
private boolean shouldCheckWhetherGemFireServerIsRunning(Object bean, String beanName) {
return (isGemFireRegion(bean, beanName)
? checkGemFireServerIsRunning.compareAndSet(true, false)
: whenGemFireCache(bean, beanName));
}
private boolean isGemFireRegion(Object bean, String beanName) {
return (GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME.equals(beanName)
|| bean instanceof Region);
}
private boolean whenGemFireCache(Object bean, String beanName) {
if (bean instanceof ClientCache) {
defaultPool.compareAndSet(null, ((ClientCache) bean).getDefaultPool());
}
return false;
}
private void validateCacheClientNotified() throws InterruptedException {
boolean didNotTimeout = LATCH.await(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS);
Assert.state(didNotTimeout, String.format(
"GemFire Cache Server failed to start on host [%s] and port [%d]", host, port));
}
@SuppressWarnings("all")
private void validateCacheClientSubscriptionQueueConnectionEstablished() throws InterruptedException {
boolean cacheClientSubscriptionQueueConnectionEstablished = false;
Pool pool = defaultIfNull(this.defaultPool.get(), GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME,
GEMFIRE_DEFAULT_POOL_NAME);
if (pool instanceof PoolImpl) {
long timeout = (System.currentTimeMillis() + DEFAULT_TIMEOUT);
while (System.currentTimeMillis() < timeout
&& !((PoolImpl) pool).isPrimaryUpdaterAlive()) {
synchronized (pool) {
TimeUnit.MILLISECONDS.timedWait(pool, 500L);
}
}
cacheClientSubscriptionQueueConnectionEstablished |=
((PoolImpl) pool).isPrimaryUpdaterAlive();
}
Assert.state(cacheClientSubscriptionQueueConnectionEstablished, String.format(
"Cache client subscription queue connection not established; GemFire Pool was [%s];"
+ " GemFire Pool configuration was [locators = %s, servers = %s]",
pool, pool.getLocators(), pool.getServers()));
}
private Pool defaultIfNull(Pool pool, String... poolNames) {
for (String poolName : poolNames) {
pool = (pool != null ? pool : PoolManager.find(poolName));
}
return pool;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
};
}

View File

@@ -37,8 +37,7 @@ import org.springframework.session.data.gemfire.config.annotation.web.http.Enabl
* @see org.springframework.boot.SpringApplication
* @see org.springframework.boot.autoconfigure.SpringBootApplication
* @see org.springframework.context.annotation.Bean
* @see org.springframework.session.data.gemfire.config.annotation.web.http.
* EnableGemFireHttpSession
* @see org.springframework.session.data.gemfire.config.annotation.web.http.EnableGemFireHttpSession
* @see com.gemstone.gemfire.cache.Cache
* @since 1.2.1
*/
@@ -64,7 +63,7 @@ public class GemFireServer {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName());
gemfireProperties.setProperty("mcast-port", "0");
//gemfireProperties.setProperty("log-file", "gemfire-server.log");
gemfireProperties.setProperty("log-level", logLevel());
//gemfireProperties.setProperty("jmx-manager", "true");
//gemfireProperties.setProperty("jmx-manager-start", "true");
@@ -73,11 +72,11 @@ public class GemFireServer {
}
String applicationName() {
return "samples:httpsession-gemfire-boot:".concat(getClass().getSimpleName());
return "spring-session-data-gemfire-boot-sample:".concat(getClass().getSimpleName());
}
String logLevel() {
return System.getProperty("gemfire.log-level", DEFAULT_GEMFIRE_LOG_LEVEL);
return System.getProperty("spring-session-data-gemfire.log.level", DEFAULT_GEMFIRE_LOG_LEVEL);
}
@Bean
@@ -92,9 +91,9 @@ public class GemFireServer {
@Bean
CacheServerFactoryBean gemfireCacheServer(Cache gemfireCache,
@Value("${gemfire.cache.server.bind-address:localhost}") String bindAddress,
@Value("${gemfire.cache.server.hostname-for-clients:localhost}") String hostnameForClients,
@Value("${gemfire.cache.server.port:12480}") int port) { // <4>
@Value("${spring-session-data-gemfire.cache.server.bind-address:localhost}") String bindAddress,
@Value("${spring-session-data-gemfire.cache.server.hostname-for-clients:localhost}") String hostnameForClients,
@Value("${spring-session-data-gemfire.cache.server.port:12480}") int port) { // <4>
CacheServerFactoryBean gemfireCacheServer = new CacheServerFactoryBean();

View File

@@ -0,0 +1,186 @@
/*
* 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 sample.server;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.ExpirationAction;
import com.gemstone.gemfire.cache.ExpirationAttributes;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionFactory;
import com.gemstone.gemfire.cache.RegionShortcut;
import com.gemstone.gemfire.cache.server.CacheServer;
import org.springframework.session.data.gemfire.AbstractGemFireOperationsSessionRepository;
import org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration;
import org.springframework.util.StringUtils;
/**
* The {@link NativeGemFireServer} class uses the GemFire API to create a GemFire (cache) instance.
*
* @author John Blum
* @see com.gemstone.gemfire.cache.Cache
* @see com.gemstone.gemfire.cache.Region
* @see com.gemstone.gemfire.cache.server.CacheServer
* @see org.springframework.session.data.gemfire.config.annotation.web.http.GemFireHttpSessionConfiguration
* @since 1.3.0
*/
@SuppressWarnings("unused")
public final class NativeGemFireServer implements Runnable {
private static final int GEMFIRE_CACHE_SERVER_PORT =
Integer.getInteger("spring-session-data-gemfire.cache.server.port", 12480);
private static final String GEMFIRE_CACHE_SERVER_HOST = "localhost";
private static final String GEMFIRE_CACHE_SERVER_HOSTNAME_FOR_CLIENTS = GEMFIRE_CACHE_SERVER_HOST;
private static final String GEMFIRE_LOG_FILENAME_PATTERN =
String.format("%s", NativeGemFireServer.class.getSimpleName()).concat("-%s.log");
public static void main(String[] args) {
newNativeGemFireServer(args).run();
}
private final String[] args;
private static File newGemFireLogFile(String suffix) {
return new File(String.format(GEMFIRE_LOG_FILENAME_PATTERN, suffix));
}
private static NativeGemFireServer newNativeGemFireServer(String[] args) {
return new NativeGemFireServer(args);
}
private static String[] nullSafeStringArray(String[] array) {
return (array != null ? array.clone() : new String[0]);
}
private static void writeStringTo(File file, String fileContents) {
PrintWriter fileWriter = null;
try {
fileWriter = new PrintWriter(new BufferedWriter(new FileWriter(file, true)), true);
fileWriter.println(fileContents);
fileWriter.flush();
}
catch (IOException e) {
throw new RuntimeException(String.format("Failed to write [%s] to file [%s]", fileContents, file), e);
}
finally {
if (fileWriter != null) {
fileWriter.close();
}
}
}
private NativeGemFireServer(String[] args) {
this.args = nullSafeStringArray(args);
}
/**
* @inheritDoc
*/
public void run() {
run(this.args);
}
private void run(String[] args) {
try {
writeStringTo(newGemFireLogFile("stdout"), "Before");
registerShutdownHook(addCacheServer(createRegion(gemfireCache(
gemfireProperties(applicationName())))));
writeStringTo(newGemFireLogFile("stdout"), "After");
}
catch (Throwable e) {
writeStringTo(newGemFireLogFile("stderr"), e.toString());
}
}
private String applicationName() {
return applicationName(null);
}
private String applicationName(String applicationName) {
return StringUtils.hasText(applicationName) ? applicationName
: "spring-session-data-gemfire.boot.sample." + NativeGemFireServer.class.getSimpleName();
}
private Properties gemfireProperties(String applicationName) {
Properties gemfireProperties = new Properties();
gemfireProperties.setProperty("name", applicationName);
gemfireProperties.setProperty("log-file", "gemfire-server.log");
gemfireProperties.setProperty("log-level", "config");
//gemfireProperties.setProperty("jmx-manager", "true");
//gemfireProperties.setProperty("jmx-manager-start", "true");
return gemfireProperties;
}
private Cache gemfireCache(Properties gemfireProperties) {
return new CacheFactory(gemfireProperties).create();
}
private Cache createRegion(Cache gemfireCache) {
RegionFactory<Object, AbstractGemFireOperationsSessionRepository.GemFireSession> regionFactory =
gemfireCache.createRegionFactory(RegionShortcut.PARTITION);
regionFactory.setKeyConstraint(Object.class);
regionFactory.setValueConstraint(AbstractGemFireOperationsSessionRepository.GemFireSession.class);
regionFactory.setStatisticsEnabled(true);
regionFactory.setEntryIdleTimeout(newExpirationAttributes(1800, ExpirationAction.INVALIDATE));
Region region = regionFactory.create(
GemFireHttpSessionConfiguration.DEFAULT_SPRING_SESSION_GEMFIRE_REGION_NAME);
return gemfireCache;
}
private ExpirationAttributes newExpirationAttributes(int expirationTime, ExpirationAction expirationAction) {
return new ExpirationAttributes(expirationTime, expirationAction);
}
private Cache addCacheServer(Cache gemfireCache) throws IOException {
CacheServer cacheServer = gemfireCache.addCacheServer();
cacheServer.setBindAddress(GEMFIRE_CACHE_SERVER_HOST);
cacheServer.setHostnameForClients(GEMFIRE_CACHE_SERVER_HOSTNAME_FOR_CLIENTS);
cacheServer.setPort(GEMFIRE_CACHE_SERVER_PORT);
cacheServer.start();
return gemfireCache;
}
private Cache registerShutdownHook(final Cache gemfireCache) {
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
public void run() {
if (gemfireCache != null) {
gemfireCache.close();
}
}
}));
return gemfireCache;
}
}

View File

@@ -1,6 +1,7 @@
buildscript {
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
@@ -14,8 +15,6 @@ apply from: SAMPLE_GRADLE
group = 'samples'
ext['spring-security.version'] = springSecurityVersion
dependencies {
compile project(':spring-session-jdbc'),
"org.springframework.boot:spring-boot-starter-jdbc",
@@ -29,10 +28,10 @@ dependencies {
"org.webjars:webjars-locator",
"com.h2database:h2"
testCompile "org.springframework.boot:spring-boot-starter-test"
testCompile "org.springframework.boot:spring-boot-starter-test",
"org.assertj:assertj-core:$assertjVersion"
integrationTestCompile gebDependencies,
"org.spockframework:spock-spring:$spockVersion"
integrationTestCompile seleniumDependencies
}

View File

@@ -0,0 +1,82 @@
/*
* Copyright 2014-2017 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 sample;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.WebDriver;
import sample.pages.HomePage;
import sample.pages.LoginPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
/**
* @author Eddú Meléndez
*/
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
public class BootTests {
@Autowired
private MockMvc mockMvc;
private WebDriver driver;
@Before
public void setup() {
this.driver = MockMvcHtmlUnitDriverBuilder.mockMvcSetup(this.mockMvc).build();
}
@After
public void tearDown() {
this.driver.quit();
}
@Test
public void home() {
LoginPage login = HomePage.go(this.driver);
login.assertAt();
HomePage home = login.form().login(HomePage.class);
home.assertAt();
}
@Test
public void login() {
LoginPage login = HomePage.go(this.driver);
HomePage home = login.form().login(HomePage.class);
home.containCookie("SESSION");
home.doesNotContainCookie("JSESSIONID");
}
@Test
public void logout() {
LoginPage login = HomePage.go(this.driver);
HomePage home = login.form().login(HomePage.class);
login = home.logout();
login.assertAt();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2016 the original author or authors.
* Copyright 2014-2017 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.
@@ -14,20 +14,28 @@
* limitations under the License.
*/
package sample.pages
package sample.pages;
import geb.Page
import org.openqa.selenium.WebDriver;
/**
* The home page
*
* @author Rob Winch
* @author Eddú Meléndez
*/
class HomePage extends Page {
static url = ''
static at = { assert driver.title == 'Secured Content'; true}
static content = {
username { $('#un').text() }
logout(to:LoginPage) { $('input[type=submit]').click() }
public class BasePage {
private WebDriver driver;
public BasePage(WebDriver driver) {
this.driver = driver;
}
public WebDriver getDriver() {
return this.driver;
}
public static void get(WebDriver driver, String get) {
String baseUrl = "http://localhost";
driver.get(baseUrl + get);
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2014-2017 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 sample.pages;
import java.util.Set;
import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.PageFactory;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Eddú Meléndez
*/
public class HomePage extends BasePage {
public HomePage(WebDriver driver) {
super(driver);
}
public static LoginPage go(WebDriver driver) {
get(driver, "/");
return PageFactory.initElements(driver, LoginPage.class);
}
public void assertAt() {
assertThat(getDriver().getTitle()).isEqualTo("Spring Session Sample - Secured Content");
}
public void containCookie(String cookieName) {
Set<Cookie> cookies = getDriver().manage().getCookies();
assertThat(cookies).extracting("name").contains(cookieName);
}
public void doesNotContainCookie(String cookieName) {
Set<Cookie> cookies = getDriver().manage().getCookies();
assertThat(cookies).extracting("name").doesNotContain(cookieName);
}
public LoginPage logout() {
WebElement logout = getDriver().findElement(By.cssSelector("input[type=\"submit\"]"));
logout.click();
return PageFactory.initElements(getDriver(), LoginPage.class);
}
}

View File

@@ -0,0 +1,69 @@
/*
* Copyright 2014-2017 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 sample.pages;
import org.openqa.selenium.SearchContext;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.pagefactory.DefaultElementLocatorFactory;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Eddú Meléndez
* @author Rob Winch
*/
public class LoginPage extends BasePage {
public LoginPage(WebDriver driver) {
super(driver);
}
public void assertAt() {
assertThat(getDriver().getTitle()).isEqualTo("Login Page");
}
public Form form() {
return new Form(getDriver());
}
public class Form {
@FindBy(name = "username")
private WebElement username;
@FindBy(name = "password")
private WebElement password;
@FindBy(name = "submit")
private WebElement button;
public Form(SearchContext context) {
PageFactory.initElements(new DefaultElementLocatorFactory(context), this);
}
public <T> T login(Class<T> page) {
this.username.sendKeys("user");
this.password.sendKeys("password");
this.button.click();
return PageFactory.initElements(getDriver(), page);
}
}
}

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -1,6 +1,7 @@
buildscript {
repositories {
mavenCentral()
maven { url "https://repo.spring.io/milestone" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:$springBootVersion")
@@ -14,8 +15,6 @@ apply from: SAMPLE_GRADLE
group = 'samples'
ext['spring-security.version'] = springSecurityVersion
dependencies {
compile project(':spring-session'),
"org.springframework.boot:spring-boot-starter-data-mongodb",
@@ -31,8 +30,7 @@ dependencies {
testCompile "org.springframework.boot:spring-boot-starter-test"
integrationTestCompile gebDependencies,
"org.spockframework:spock-spring:$spockVersion"
integrationTestCompile seleniumDependencies
}
@@ -40,9 +38,6 @@ integrationTest {
doFirst {
def port = reservePort()
def host = 'localhost:' + port
systemProperties['geb.build.baseUrl'] = 'http://'+host+'/'
systemProperties['geb.build.reportsDir'] = 'build/geb-reports'
systemProperties['server.port'] = port
systemProperties['management.port'] = 0

View File

@@ -0,0 +1,104 @@
/*
* Copyright 2014-2017 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 sample;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openqa.selenium.By;
import org.openqa.selenium.Cookie;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import sample.pages.HomePage;
import sample.pages.LoginPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Pool Dolorier
*/
@RunWith(SpringRunner.class)
@AutoConfigureMockMvc
@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
public class BootTests {
@Autowired
private MockMvc mockMvc;
private WebDriver driver;
@Before
public void setUp() {
this.driver = MockMvcHtmlUnitDriverBuilder
.mockMvcSetup(this.mockMvc)
.build();
}
@After
public void tearDown() {
this.driver.quit();
}
@Test
public void unauthenticatedUserSentToLogInPage() {
HomePage homePage = HomePage.go(this.driver);
LoginPage loginPage = homePage.unauthenticated();
loginPage.assertAt();
}
@Test
public void logInViewsHomePage() {
LoginPage loginPage = LoginPage.go(this.driver);
loginPage.assertAt();
HomePage homePage = loginPage.login("user", "password");
homePage.assertAt();
WebElement username = homePage.getDriver().findElement(By.id("un"));
assertThat(username.getText()).isEqualTo("user");
Set<Cookie> cookies = homePage.getDriver().manage().getCookies();
assertThat(cookies).extracting("name").contains("SESSION");
assertThat(cookies).extracting("name").doesNotContain("JSESSIONID");
}
@Test
public void logoutSuccess() {
LoginPage loginPage = LoginPage.go(this.driver);
HomePage homePage = loginPage.login("user", "password");
LoginPage successLogoutPage = homePage.logout();
successLogoutPage.assertAt();
}
@Test
public void loggedOutUserSentToLoginPage() {
LoginPage loginPage = LoginPage.go(this.driver);
HomePage homePage = loginPage.login("user", "password");
homePage.logout();
HomePage backHomePage = HomePage.go(this.driver);
LoginPage backLoginPage = backHomePage.unauthenticated();
backLoginPage.assertAt();
}
}

View File

@@ -0,0 +1,40 @@
/*
* Copyright 2014-2017 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 sample.pages;
import org.openqa.selenium.WebDriver;
/**
* @author Pool Dolorier
*/
public abstract class BasePage {
private WebDriver driver;
public BasePage(WebDriver driver) {
this.driver = driver;
}
public WebDriver getDriver() {
return this.driver;
}
public static void get(WebDriver driver, String get) {
String baseUrl = "http://localhost";
driver.get(baseUrl + get);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2014-2017 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 sample.pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Pool Dolorier
*/
public class HomePage extends BasePage {
@FindBy(css = "input[type='submit']")
private WebElement submit;
public HomePage(WebDriver driver) {
super(driver);
}
public static HomePage go(WebDriver driver) {
get(driver, "/");
return PageFactory.initElements(driver, HomePage.class);
}
public LoginPage unauthenticated() {
return LoginPage.go(getDriver());
}
public LoginPage logout() {
this.submit.click();
return LoginPage.go(getDriver());
}
public void assertAt() {
assertThat(getDriver().getTitle()).isEqualTo("Spring Session Sample - Secured Content");
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright 2014-2017 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 sample.pages;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import static org.assertj.core.api.Assertions.assertThat;
/**
* @author Pool Dolorier
*/
public class LoginPage extends BasePage {
@FindBy(name = "username")
private WebElement username;
@FindBy(name = "password")
private WebElement password;
@FindBy(css = "input[name='submit']")
private WebElement submit;
public LoginPage(WebDriver driver) {
super(driver);
}
public static LoginPage go(WebDriver driver) {
get(driver, "/login");
return PageFactory.initElements(driver, LoginPage.class);
}
public void assertAt() {
assertThat(getDriver().getTitle()).isEqualTo("Login Page");
}
public HomePage login(String user, String password) {
this.username.sendKeys(user);
this.password.sendKeys(password);
this.submit.click();
return HomePage.go(getDriver());
}
}

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