diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java index d61fdef35d6..7663ea584f5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/BeanDefinition.java @@ -238,6 +238,7 @@ public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement { /** * Return whether this a Prototype, with an independent instance * returned for each call. + * @since 3.0 * @see #SCOPE_PROTOTYPE */ boolean isPrototype(); diff --git a/spring-context/src/test/java/org/springframework/context/annotation/DestroyMethodInferenceTests.java b/spring-context/src/test/java/org/springframework/context/annotation/DestroyMethodInferenceTests.java index a9b1bf88297..e0aad307a64 100644 --- a/spring-context/src/test/java/org/springframework/context/annotation/DestroyMethodInferenceTests.java +++ b/spring-context/src/test/java/org/springframework/context/annotation/DestroyMethodInferenceTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-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. @@ -36,8 +36,7 @@ public class DestroyMethodInferenceTests { @Test public void beanMethods() { - ConfigurableApplicationContext ctx = - new AnnotationConfigApplicationContext(Config.class); + ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class); WithExplicitDestroyMethod c0 = ctx.getBean(WithExplicitDestroyMethod.class); WithLocalCloseMethod c1 = ctx.getBean("c1", WithLocalCloseMethod.class); WithLocalCloseMethod c2 = ctx.getBean("c2", WithLocalCloseMethod.class); @@ -91,9 +90,11 @@ public class DestroyMethodInferenceTests { assertThat(x8.closed, is(false)); } + @Configuration static class Config { - @Bean(destroyMethod="explicitClose") + + @Bean(destroyMethod = "explicitClose") public WithExplicitDestroyMethod c0() { return new WithExplicitDestroyMethod(); } @@ -118,12 +119,12 @@ public class DestroyMethodInferenceTests { return new WithInheritedCloseMethod(); } - @Bean(destroyMethod="other") + @Bean(destroyMethod = "other") public WithInheritedCloseMethod c5() { return new WithInheritedCloseMethod() { @Override public void close() throws IOException { - throw new RuntimeException("close() should not be called"); + throw new IllegalStateException("close() should not be called"); } @SuppressWarnings("unused") public void other() { @@ -150,33 +151,46 @@ public class DestroyMethodInferenceTests { static class WithExplicitDestroyMethod { + boolean closed = false; + public void explicitClose() { closed = true; } } + static class WithLocalCloseMethod { + boolean closed = false; + public void close() { closed = true; } } + static class WithInheritedCloseMethod implements Closeable { + boolean closed = false; + @Override public void close() throws IOException { closed = true; } } + static class WithNoCloseMethod { + boolean closed = false; } + static class WithLocalShutdownMethod { + boolean closed = false; + public void shutdown() { closed = true; } diff --git a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java index 60df8aacde6..a50f87d79e3 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/simp/stomp/StompHeaderAccessor.java @@ -268,7 +268,7 @@ public class StompHeaderAccessor extends SimpMessageHeaderAccessor { } @Override - public void setSubscriptionId(String subscriptionId) { + public void setSubscriptionId(@Nullable String subscriptionId) { super.setSubscriptionId(subscriptionId); trySetStompHeaderForSubscriptionId(); } diff --git a/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java b/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java index 51fb5b7239e..679666a84cc 100644 --- a/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java +++ b/spring-web/src/main/java/org/springframework/http/server/reactive/ReactorServerHttpRequest.java @@ -58,9 +58,7 @@ public class ReactorServerHttpRequest extends AbstractServerHttpRequest { private static URI initUri(HttpServerRequest request) throws URISyntaxException { Assert.notNull(request, "'request' must not be null"); - URI baseUri = resolveBaseUrl(request); - String requestUri = request.uri(); - return (baseUri != null ? new URI(baseUri.toString() + requestUri) : new URI(requestUri)); + return new URI(resolveBaseUrl(request).toString() + request.uri()); } private static URI resolveBaseUrl(HttpServerRequest request) throws URISyntaxException { @@ -69,14 +67,16 @@ public class ReactorServerHttpRequest extends AbstractServerHttpRequest { final int portIndex; if (header.startsWith("[")) { portIndex = header.indexOf(':', header.indexOf(']')); - } else { + } + else { portIndex = header.indexOf(':'); } if (portIndex != -1) { try { return new URI(null, null, header.substring(0, portIndex), Integer.parseInt(header.substring(portIndex + 1)), null, null, null); - } catch (NumberFormatException ignore) { + } + catch (NumberFormatException ex) { throw new URISyntaxException(header, "Unable to parse port", portIndex); } } diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptor.java b/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptor.java index e1c752cafe9..8d4cd43a3ec 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptor.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptor.java @@ -45,10 +45,23 @@ import org.springframework.web.context.request.NativeWebRequest; */ public interface CallableProcessingInterceptor { + /** + * Constant indicating that no result has been determined by this + * interceptor, giving subsequent interceptors a chance. + * @see #handleTimeout + * @see #handleError + */ Object RESULT_NONE = new Object(); + /** + * Constant indicating that the response has been handled by this interceptor + * without a result and that no further interceptors are to be invoked. + * @see #handleTimeout + * @see #handleError + */ Object RESPONSE_HANDLED = new Object(); + /** * Invoked before the start of concurrent handling in the original * thread in which the {@code Callable} is submitted for concurrent handling. @@ -58,6 +71,7 @@ public interface CallableProcessingInterceptor { * {@link #preProcess(NativeWebRequest, Callable)}. Capturing the state of * Spring Security's SecurityContextHolder and migrating it to the new Thread * is a concrete example of where this is useful. + *

The default implementation is empty. * @param request the current request * @param task the task for the current async request * @throws Exception in case of errors @@ -69,6 +83,7 @@ public interface CallableProcessingInterceptor { * Invoked after the start of concurrent handling in the async * thread in which the {@code Callable} is executed and before the * actual invocation of the {@code Callable}. + *

The default implementation is empty. * @param request the current request * @param task the task for the current async request * @throws Exception in case of errors @@ -81,6 +96,7 @@ public interface CallableProcessingInterceptor { * async thread in which the {@code Callable} is executed. This method may * be invoked later than {@code afterTimeout} or {@code afterCompletion} * depending on when the {@code Callable} finishes processing. + *

The default implementation is empty. * @param request the current request * @param task the task for the current async request * @param concurrentResult the result of concurrent processing, which could @@ -96,6 +112,7 @@ public interface CallableProcessingInterceptor { * the {@code Callable} task completes. Implementations may return a value, * including an {@link Exception}, to use instead of the value the * {@link Callable} did not return in time. + *

The default implementation always returns {@link #RESULT_NONE}. * @param request the current request * @param task the task for the current async request * @return a concurrent result value; if the value is anything other than @@ -112,6 +129,7 @@ public interface CallableProcessingInterceptor { * the async request before the {@code Callable} task completes. * Implementations may return a value, including an {@link Exception}, to * use instead of the value the {@link Callable} did not return in time. + *

The default implementation always returns {@link #RESULT_NONE}. * @param request the current request * @param task the task for the current async request * @param t the error that occurred while request processing @@ -128,6 +146,7 @@ public interface CallableProcessingInterceptor { /** * Invoked from a container thread when async processing completes for any * reason including timeout or network error. + *

The default implementation is empty. * @param request the current request * @param task the task for the current async request * @throws Exception in case of errors diff --git a/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptorAdapter.java b/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptorAdapter.java index 80616dcb8c0..79f9ac027e7 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptorAdapter.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/async/CallableProcessingInterceptorAdapter.java @@ -32,48 +32,28 @@ import org.springframework.web.context.request.NativeWebRequest; @Deprecated public abstract class CallableProcessingInterceptorAdapter implements CallableProcessingInterceptor { - /** - * This implementation is empty. - */ @Override public void beforeConcurrentHandling(NativeWebRequest request, Callable task) throws Exception { } - /** - * This implementation is empty. - */ @Override public void preProcess(NativeWebRequest request, Callable task) throws Exception { } - /** - * This implementation is empty. - */ @Override public void postProcess(NativeWebRequest request, Callable task, Object concurrentResult) throws Exception { } - /** - * This implementation always returns - * {@link CallableProcessingInterceptor#RESULT_NONE RESULT_NONE}. - */ @Override public Object handleTimeout(NativeWebRequest request, Callable task) throws Exception { return RESULT_NONE; } - /** - * This implementation always returns - * {@link CallableProcessingInterceptor#RESULT_NONE RESULT_NONE}. - */ @Override public Object handleError(NativeWebRequest request, Callable task, Throwable t) throws Exception { return RESULT_NONE; } - /** - * This implementation is empty. - */ @Override public void afterCompletion(NativeWebRequest request, Callable task) throws Exception { } diff --git a/spring-web/src/test/java/org/springframework/http/server/reactive/AsyncIntegrationTests.java b/spring-web/src/test/java/org/springframework/http/server/reactive/AsyncIntegrationTests.java index 44f639fb429..3cb85ff6ff7 100644 --- a/spring-web/src/test/java/org/springframework/http/server/reactive/AsyncIntegrationTests.java +++ b/spring-web/src/test/java/org/springframework/http/server/reactive/AsyncIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-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. @@ -20,6 +20,7 @@ import java.net.URI; import java.time.Duration; import org.hamcrest.Matchers; +import org.junit.Ignore; import org.junit.Test; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -32,7 +33,7 @@ import org.springframework.http.RequestEntity; import org.springframework.http.ResponseEntity; import org.springframework.web.client.RestTemplate; -import static org.junit.Assert.assertThat; +import static org.junit.Assert.*; /** * @author Stephane Maldini @@ -44,12 +45,14 @@ public class AsyncIntegrationTests extends AbstractHttpHandlerIntegrationTests { private final DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory(); + @Override protected AsyncHandler createHttpHandler() { return new AsyncHandler(); } @Test + @Ignore // TODO: fragile due to socket failures public void basicTest() throws Exception { URI url = new URI("http://localhost:" + port); ResponseEntity response = new RestTemplate().exchange( @@ -58,6 +61,7 @@ public class AsyncIntegrationTests extends AbstractHttpHandlerIntegrationTests { assertThat(response.getBody(), Matchers.equalTo("hello")); } + private class AsyncHandler implements HttpHandler { @Override diff --git a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java index 1ead7ecda47..697425cb4c6 100644 --- a/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java +++ b/spring-webflux/src/main/java/org/springframework/web/reactive/function/server/DefaultHandlerStrategiesBuilder.java @@ -24,7 +24,6 @@ import java.util.function.Consumer; import org.springframework.http.codec.HttpMessageReader; import org.springframework.http.codec.HttpMessageWriter; import org.springframework.http.codec.ServerCodecConfigurer; -import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.web.reactive.result.view.ViewResolver; import org.springframework.web.server.WebExceptionHandler; @@ -49,8 +48,7 @@ class DefaultHandlerStrategiesBuilder implements HandlerStrategies.Builder { private final List exceptionHandlers = new ArrayList<>(); - @Nullable - private LocaleContextResolver localeContextResolver; + private LocaleContextResolver localeContextResolver = new AcceptHeaderLocaleContextResolver(); public DefaultHandlerStrategiesBuilder() { @@ -119,7 +117,6 @@ class DefaultHandlerStrategiesBuilder implements HandlerStrategies.Builder { private final List exceptionHandlers; - @Nullable private final LocaleContextResolver localeContextResolver; public DefaultHandlerStrategies( @@ -128,7 +125,7 @@ class DefaultHandlerStrategiesBuilder implements HandlerStrategies.Builder { List viewResolvers, List webFilters, List exceptionHandlers, - @Nullable LocaleContextResolver localeContextResolver) { + LocaleContextResolver localeContextResolver) { this.messageReaders = unmodifiableCopy(messageReaders); this.messageWriters = unmodifiableCopy(messageWriters);