Polishing

This commit is contained in:
Juergen Hoeller 2014-09-26 22:38:41 +02:00
parent a6e1c53f23
commit 7f9baa3a09
4 changed files with 30 additions and 39 deletions

View File

@ -58,7 +58,7 @@ import org.springframework.util.ObjectUtils;
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.0 * @since 2.0
* @see #setPoolSize * @see #setPoolSize
* @see #setRemoveOnCancelPolicy(boolean) * @see #setRemoveOnCancelPolicy
* @see #setThreadFactory * @see #setThreadFactory
* @see ScheduledExecutorTask * @see ScheduledExecutorTask
* @see java.util.concurrent.ScheduledExecutorService * @see java.util.concurrent.ScheduledExecutorService
@ -68,17 +68,17 @@ import org.springframework.util.ObjectUtils;
public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport
implements FactoryBean<ScheduledExecutorService> { implements FactoryBean<ScheduledExecutorService> {
// ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 1.7+ // ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 7+
private static final boolean setRemoveOnCancelPolicyAvailable = private static final boolean setRemoveOnCancelPolicyAvailable =
ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class); ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class);
private int poolSize = 1; private int poolSize = 1;
private boolean removeOnCancelPolicy;
private ScheduledExecutorTask[] scheduledExecutorTasks; private ScheduledExecutorTask[] scheduledExecutorTasks;
private boolean removeOnCancelPolicy = false;
private boolean continueScheduledExecutionAfterException = false; private boolean continueScheduledExecutionAfterException = false;
private boolean exposeUnconfigurableExecutor = false; private boolean exposeUnconfigurableExecutor = false;
@ -95,14 +95,6 @@ public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport
this.poolSize = poolSize; this.poolSize = poolSize;
} }
/**
* Set the same property on ScheduledExecutorService (JDK 1.7+).
* There is no default. If not set, the executor property is not set.
*/
public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
this.removeOnCancelPolicy = removeOnCancelPolicy;
}
/** /**
* Register a list of ScheduledExecutorTask objects with the ScheduledExecutorService * Register a list of ScheduledExecutorTask objects with the ScheduledExecutorService
* that this FactoryBean creates. Depending on each ScheduledExecutorTask's settings, * that this FactoryBean creates. Depending on each ScheduledExecutorTask's settings,
@ -115,6 +107,15 @@ public class ScheduledExecutorFactoryBean extends ExecutorConfigurationSupport
this.scheduledExecutorTasks = scheduledExecutorTasks; this.scheduledExecutorTasks = scheduledExecutorTasks;
} }
/**
* Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor} (JDK 7+).
* <p>Default is {@code false}. If set to {@code true}, the target executor will be
* switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
*/
public void setRemoveOnCancelPolicy(boolean removeOnCancelPolicy) {
this.removeOnCancelPolicy = removeOnCancelPolicy;
}
/** /**
* Specify whether to continue the execution of a scheduled task * Specify whether to continue the execution of a scheduled task
* after it threw an exception. * after it threw an exception.

View File

@ -58,14 +58,14 @@ import org.springframework.util.concurrent.ListenableFutureTask;
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler { implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, TaskScheduler {
// ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 1.7+ // ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(boolean) only available on JDK 7+
private static final boolean setRemoveOnCancelPolicyAvailable = private static final boolean setRemoveOnCancelPolicyAvailable =
ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class); ClassUtils.hasMethod(ScheduledThreadPoolExecutor.class, "setRemoveOnCancelPolicy", boolean.class);
private volatile int poolSize = 1; private volatile int poolSize = 1;
private volatile boolean removeOnCancelPolicy; private volatile boolean removeOnCancelPolicy = false;
private volatile ScheduledExecutorService scheduledExecutor; private volatile ScheduledExecutorService scheduledExecutor;
@ -86,8 +86,9 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
} }
/** /**
* Set the same property on ScheduledExecutorService (JDK 1.7+). * Set the remove-on-cancel mode on {@link ScheduledThreadPoolExecutor} (JDK 7+).
* There is no default. If not set, the executor property is not set. * <p>Default is {@code false}. If set to {@code true}, the target executor will be
* switched into remove-on-cancel mode (if possible, with a soft fallback otherwise).
* <p><b>This setting can be modified at runtime, for example through JMX.</b> * <p><b>This setting can be modified at runtime, for example through JMX.</b>
*/ */
@UsesJava7 @UsesJava7
@ -183,14 +184,17 @@ public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
} }
/** /**
* Return the current setting of removeOnCancelPolicy. * Return the current setting for the remove-on-cancel mode.
* <p>Requires an underlying {@link ScheduledThreadPoolExecutor} and JDK 1.7+. * <p>Requires an underlying {@link ScheduledThreadPoolExecutor}.
*/ */
@UsesJava7 @UsesJava7
public boolean isRemoveOnCancelPolicy() { public boolean isRemoveOnCancelPolicy() {
if (!setRemoveOnCancelPolicyAvailable) {
return false;
}
if (this.scheduledExecutor == null) { if (this.scheduledExecutor == null) {
// Not initialized yet: return our setting for the time being. // Not initialized yet: return our setting for the time being.
return (setRemoveOnCancelPolicyAvailable && this.removeOnCancelPolicy); return this.removeOnCancelPolicy;
} }
return getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy(); return getScheduledThreadPoolExecutor().getRemoveOnCancelPolicy();
} }

View File

@ -81,11 +81,9 @@ public class SockJsServiceRegistration {
* iframe so that code in the iframe can run from a domain local to the SockJS * iframe so that code in the iframe can run from a domain local to the SockJS
* server. Since the iframe needs to load the SockJS javascript client library, * server. Since the iframe needs to load the SockJS javascript client library,
* this property allows specifying where to load it from. * this property allows specifying where to load it from.
*
* <p>By default this is set to point to * <p>By default this is set to point to
* "https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js". However it can * "https://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js". However it can
* also be set to point to a URL served by the application. * also be set to point to a URL served by the application.
*
* <p>Note that it's possible to specify a relative URL in which case the URL * <p>Note that it's possible to specify a relative URL in which case the URL
* must be relative to the iframe URL. For example assuming a SockJS endpoint * must be relative to the iframe URL. For example assuming a SockJS endpoint
* mapped to "/sockjs", and resulting iframe URL "/sockjs/iframe.html", then the * mapped to "/sockjs", and resulting iframe URL "/sockjs/iframe.html", then the

View File

@ -17,12 +17,12 @@
package org.springframework.web.socket.sockjs.support; package org.springframework.web.socket.sockjs.support;
import java.io.IOException; import java.io.IOException;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.server.ServerHttpRequest; import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse; import org.springframework.http.server.ServerHttpResponse;
@ -55,6 +55,7 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
this.service = new TestSockJsService(new ThreadPoolTaskScheduler()); this.service = new TestSockJsService(new ThreadPoolTaskScheduler());
} }
@Test @Test
public void validateRequest() throws Exception { public void validateRequest() throws Exception {
@ -76,7 +77,6 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
@Test @Test
public void handleInfoGet() throws Exception { public void handleInfoGet() throws Exception {
resetResponseAndHandleRequest("GET", "/echo/info", HttpStatus.OK); resetResponseAndHandleRequest("GET", "/echo/info", HttpStatus.OK);
assertEquals("application/json;charset=UTF-8", this.servletResponse.getContentType()); assertEquals("application/json;charset=UTF-8", this.servletResponse.getContentType());
@ -98,9 +98,7 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
body.substring(body.indexOf(','))); body.substring(body.indexOf(',')));
} }
// SPR-11443 @Test // SPR-11443
@Test
public void handleInfoGetCorsFilter() throws Exception { public void handleInfoGetCorsFilter() throws Exception {
// Simulate scenario where Filter would have already set CORS headers // Simulate scenario where Filter would have already set CORS headers
@ -111,9 +109,7 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
assertEquals("foobar:123", this.servletResponse.getHeader("Access-Control-Allow-Origin")); assertEquals("foobar:123", this.servletResponse.getHeader("Access-Control-Allow-Origin"));
} }
// SPR-11919 @Test // SPR-11919
@Test
public void handleInfoGetWildflyNPE() throws Exception { public void handleInfoGetWildflyNPE() throws Exception {
HttpServletResponse mockResponse = mock(HttpServletResponse.class); HttpServletResponse mockResponse = mock(HttpServletResponse.class);
ServletOutputStream ous = mock(ServletOutputStream.class); ServletOutputStream ous = mock(ServletOutputStream.class);
@ -128,9 +124,7 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
@Test @Test
public void handleInfoOptions() throws Exception { public void handleInfoOptions() throws Exception {
this.servletRequest.addHeader("Access-Control-Request-Headers", "Last-Modified"); this.servletRequest.addHeader("Access-Control-Request-Headers", "Last-Modified");
resetResponseAndHandleRequest("OPTIONS", "/echo/info", HttpStatus.NO_CONTENT); resetResponseAndHandleRequest("OPTIONS", "/echo/info", HttpStatus.NO_CONTENT);
this.response.flush(); this.response.flush();
@ -143,7 +137,6 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
@Test @Test
public void handleIframeRequest() throws Exception { public void handleIframeRequest() throws Exception {
resetResponseAndHandleRequest("GET", "/echo/iframe.html", HttpStatus.OK); resetResponseAndHandleRequest("GET", "/echo/iframe.html", HttpStatus.OK);
assertEquals("text/html;charset=UTF-8", this.servletResponse.getContentType()); assertEquals("text/html;charset=UTF-8", this.servletResponse.getContentType());
@ -155,15 +148,12 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
@Test @Test
public void handleIframeRequestNotModified() throws Exception { public void handleIframeRequestNotModified() throws Exception {
this.servletRequest.addHeader("If-None-Match", "\"06b486b3208b085d9e3220f456a6caca4\""); this.servletRequest.addHeader("If-None-Match", "\"06b486b3208b085d9e3220f456a6caca4\"");
resetResponseAndHandleRequest("GET", "/echo/iframe.html", HttpStatus.NOT_MODIFIED); resetResponseAndHandleRequest("GET", "/echo/iframe.html", HttpStatus.NOT_MODIFIED);
} }
@Test @Test
public void handleRawWebSocketRequest() throws Exception { public void handleRawWebSocketRequest() throws Exception {
resetResponseAndHandleRequest("GET", "/echo", HttpStatus.OK); resetResponseAndHandleRequest("GET", "/echo", HttpStatus.OK);
assertEquals("Welcome to SockJS!\n", this.servletResponse.getContentAsString()); assertEquals("Welcome to SockJS!\n", this.servletResponse.getContentAsString());
@ -174,13 +164,13 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
@Test @Test
public void handleEmptyContentType() throws Exception { public void handleEmptyContentType() throws Exception {
this.servletRequest.setContentType("");
servletRequest.setContentType("");
resetResponseAndHandleRequest("GET", "/echo/info", HttpStatus.OK); resetResponseAndHandleRequest("GET", "/echo/info", HttpStatus.OK);
assertEquals("Invalid/empty content should have been ignored", 200, this.servletResponse.getStatus()); assertEquals("Invalid/empty content should have been ignored", 200, this.servletResponse.getStatus());
} }
private void resetResponseAndHandleRequest(String httpMethod, String uri, HttpStatus httpStatus) throws IOException { private void resetResponseAndHandleRequest(String httpMethod, String uri, HttpStatus httpStatus) throws IOException {
resetResponse(); resetResponse();
handleRequest(httpMethod, uri, httpStatus); handleRequest(httpMethod, uri, httpStatus);
@ -211,14 +201,12 @@ public class SockJsServiceTests extends AbstractHttpRequestTests {
@Override @Override
protected void handleRawWebSocketRequest(ServerHttpRequest req, ServerHttpResponse res, protected void handleRawWebSocketRequest(ServerHttpRequest req, ServerHttpResponse res,
WebSocketHandler handler) throws IOException { WebSocketHandler handler) throws IOException {
this.handler = handler; this.handler = handler;
} }
@Override @Override
protected void handleTransportRequest(ServerHttpRequest req, ServerHttpResponse res, WebSocketHandler handler, protected void handleTransportRequest(ServerHttpRequest req, ServerHttpResponse res, WebSocketHandler handler,
String sessionId, String transport) throws SockJsException { String sessionId, String transport) throws SockJsException {
this.sessionId = sessionId; this.sessionId = sessionId;
this.transport = transport; this.transport = transport;
this.handler = handler; this.handler = handler;