Make Servlet 2.5 compatible

Fixes gh-111 gh-182
This commit is contained in:
Rob Winch
2015-04-07 22:12:40 -05:00
parent 5417e59a50
commit 4631b57531
21 changed files with 110 additions and 30 deletions

View File

@@ -17,6 +17,8 @@ ext.springBootVersion = '1.2.3.RELEASE'
ext.JAVA_GRADLE = "$rootDir/gradle/java.gradle"
ext.MAVEN_GRADLE = "$rootDir/gradle/publish-maven.gradle"
ext.TOMCAT_GRADLE = "$rootDir/gradle/tomcat.gradle"
ext.TOMCAT_6_GRADLE = "$rootDir/gradle/tomcat6.gradle"
ext.TOMCAT_7_GRADLE = "$rootDir/gradle/tomcat7.gradle"
ext.releaseBuild = version.endsWith('RELEASE')
ext.snapshotBuild = version.endsWith('SNAPSHOT')

View File

@@ -10,15 +10,6 @@ buildscript {
apply plugin: 'war'
apply plugin: 'tomcat'
dependencies {
def tomcatVersion = '7.0.54'
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
}
}
[tomcatRun,tomcatRunWar]*.contextPath = '/'

8
gradle/tomcat6.gradle Normal file
View File

@@ -0,0 +1,8 @@
apply from: TOMCAT_GRADLE
dependencies {
def tomcatVersion = '6.0.43'
tomcat "org.apache.tomcat:catalina:${tomcatVersion}",
"org.apache.tomcat:coyote:${tomcatVersion}",
"org.apache.tomcat:jasper:${tomcatVersion}"
}

10
gradle/tomcat7.gradle Normal file
View File

@@ -0,0 +1,10 @@
apply from: TOMCAT_GRADLE
dependencies {
def tomcatVersion = '7.0.59'
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}"
tomcat("org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}") {
exclude group: 'org.eclipse.jdt.core.compiler', module: 'ecj'
}
}

View File

@@ -1,5 +1,5 @@
apply from: JAVA_GRADLE
apply from: TOMCAT_GRADLE
apply from: TOMCAT_7_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarRunner {

View File

@@ -1,5 +1,5 @@
apply from: JAVA_GRADLE
apply from: TOMCAT_GRADLE
apply from: TOMCAT_6_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarRunner {

View File

@@ -16,12 +16,10 @@
package sample;
import javax.servlet.*;
import javax.servlet.annotation.*;
import javax.servlet.http.*;
import java.io.IOException;
// tag::class[]
@WebServlet("/session")
public class SessionServlet extends HttpServlet {
@Override

View File

@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!--
- Location of the XML file that defines the root application context
- Applied by ContextLoaderListener.
-->
- Location of the XML file that defines the root application context
- Applied by ContextLoaderListener.
-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
@@ -24,14 +24,24 @@
</filter-mapping>
<!--
- Loads the root application context of this web app at startup.
- The application context is then available via
- WebApplicationContextUtils.getWebApplicationContext(servletContext).
- Loads the root application context of this web app at startup.
- The application context is then available via
- WebApplicationContextUtils.getWebApplicationContext(servletContext).
-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>session</servlet-name>
<servlet-class>sample.SessionServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>session</servlet-name>
<url-pattern>/session</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

View File

@@ -1,5 +1,5 @@
apply from: JAVA_GRADLE
apply from: TOMCAT_GRADLE
apply from: TOMCAT_7_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarRunner {

View File

@@ -1,5 +1,5 @@
apply from: JAVA_GRADLE
apply from: TOMCAT_GRADLE
apply from: TOMCAT_7_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarRunner {

View File

@@ -1,5 +1,5 @@
apply from: JAVA_GRADLE
apply from: TOMCAT_GRADLE
apply from: TOMCAT_7_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarRunner {

View File

@@ -1,5 +1,5 @@
apply from: JAVA_GRADLE
apply from: TOMCAT_GRADLE
apply from: TOMCAT_7_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false
sonarRunner {

View File

@@ -10,7 +10,7 @@ buildscript {
apply plugin: 'spring-boot'
apply from: JAVA_GRADLE
apply from: TOMCAT_GRADLE
apply from: TOMCAT_7_GRADLE
tasks.findByPath("artifactoryPublish")?.enabled = false

View File

@@ -45,11 +45,13 @@ import org.springframework.session.data.redis.config.annotation.web.http.EnableR
import org.springframework.session.events.SessionDestroyedEvent;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import redis.embedded.RedisServer;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisOperationsSessionRepositoryITests<S extends Session> {
@Autowired
private SessionRepository<S> repository;

View File

@@ -45,11 +45,13 @@ import org.springframework.session.SessionRepository;
import org.springframework.session.events.SessionDestroyedEvent;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import redis.embedded.RedisServer;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class EnableRedisHttpSessionExpireSessionDestroyedTests<S extends ExpiringSession> {
@Autowired
private SessionRepository<S> repository;

View File

@@ -19,6 +19,8 @@ import java.util.Arrays;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
@@ -99,8 +101,9 @@ public class RedisHttpSessionConfiguration implements ImportAware, BeanClassLoad
}
@Bean
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository, ServletContext servletContext) {
SessionRepositoryFilter<S> sessionRepositoryFilter = new SessionRepositoryFilter<S>(sessionRepository);
sessionRepositoryFilter.setServletContext(servletContext);
if(httpSessionStrategy != null) {
sessionRepositoryFilter.setHttpSessionStrategy(httpSessionStrategy);
}

View File

@@ -23,6 +23,7 @@ import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Pattern;
import javax.servlet.ServletRequest;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -161,6 +162,8 @@ public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy
private String sessionParam = DEFAULT_SESSION_ALIAS_PARAM_NAME;
private boolean isServlet3Plus = isServlet3();
public String getRequestedSessionId(HttpServletRequest request) {
Map<String,String> sessionIds = getSessionIds(request);
String sessionAlias = getCurrentSessionAlias(request);
@@ -215,7 +218,9 @@ public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy
private Cookie createSessionCookie(HttpServletRequest request,
Map<String, String> sessionIds) {
Cookie sessionCookie = new Cookie(cookieName,"");
sessionCookie.setHttpOnly(true);
if(isServlet3Plus) {
sessionCookie.setHttpOnly(true);
}
sessionCookie.setSecure(request.isSecure());
sessionCookie.setPath(cookiePath(request));
// TODO set domain?
@@ -387,4 +392,16 @@ public final class CookieHttpSessionStrategy implements MultiHttpSessionStrategy
throw new RuntimeException(e);
}
}
/**
* Returns true if the Servlet 3 APIs are detected.
* @return
*/
private boolean isServlet3() {
try {
ServletRequest.class.getMethod("startAsync");
return true;
} catch(NoSuchMethodException e) {}
return false;
}
}

View File

@@ -66,6 +66,8 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
private final SessionRepository<S> sessionRepository;
private ServletContext servletContext;
private MultiHttpSessionStrategy httpSessionStrategy = new CookieHttpSessionStrategy();
/**
@@ -107,7 +109,7 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
request.setAttribute(SESSION_REPOSITORY_ATTR, sessionRepository);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response);
SessionRepositoryRequestWrapper wrappedRequest = new SessionRepositoryRequestWrapper(request, response, servletContext);
SessionRepositoryResponseWrapper wrappedResponse = new SessionRepositoryResponseWrapper(wrappedRequest,response);
HttpServletRequest strategyRequest = httpSessionStrategy.wrapRequest(wrappedRequest, wrappedResponse);
@@ -120,6 +122,10 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
}
}
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
/**
* Allows ensuring that the session is saved if the response is committed.
*
@@ -158,10 +164,12 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
private HttpSessionWrapper currentSession;
private Boolean requestedSessionIdValid;
private final HttpServletResponse response;
private final ServletContext servletContext;
private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletResponse response) {
private SessionRepositoryRequestWrapper(HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) {
super(request);
this.response = response;
this.servletContext = servletContext;
}
/**
@@ -257,6 +265,14 @@ public class SessionRepositoryFilter<S extends ExpiringSession> extends OncePerR
return currentSession;
}
public ServletContext getServletContext() {
if(servletContext != null) {
return servletContext;
}
// Servlet 3.0+
return super.getServletContext();
}
@Override
public HttpSession getSession() {
return getSession(true);

View File

@@ -24,9 +24,11 @@ import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisHttpSessionConfigurationXmlCustomExpireTests {
@Test

View File

@@ -24,9 +24,11 @@ import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@WebAppConfiguration
public class RedisHttpSessionConfigurationXmlTests {
@Test

View File

@@ -50,6 +50,7 @@ import org.springframework.core.annotation.OrderUtils;
import org.springframework.mock.web.MockFilterChain;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.session.ExpiringSession;
import org.springframework.session.MapSessionRepository;
import org.springframework.session.Session;
@@ -188,6 +189,22 @@ public class SessionRepositoryFilterTests<S extends ExpiringSession> {
});
}
// gh-111
@Test
public void doFilterServletContextExplicit() throws Exception {
final ServletContext expectedContext = new MockServletContext();
filter = new SessionRepositoryFilter<ExpiringSession>(sessionRepository);
filter.setServletContext(expectedContext);
doFilter(new DoInFilter() {
@Override
public void doFilter(HttpServletRequest wrappedRequest) {
ServletContext context = wrappedRequest.getSession().getServletContext();
assertThat(context).isSameAs(expectedContext);
}
});
}
@Test
public void doFilterMaxInactiveIntervalDefault() throws Exception {
doFilter(new DoInFilter() {