From 6b7360fed1741bd9f7208f993f1df0036e2137d6 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Tue, 19 Apr 2016 15:58:24 -0400 Subject: [PATCH] Apply new ResponseStatusException hierarchy This commit replaces use of the existing ServletException-based exceptions with the new ones from ~.web.server. --- .../reactive/HandlerNotFoundException.java | 30 -------------- .../AbstractMappingContentTypeResolver.java | 12 +++--- .../accept/CompositeContentTypeResolver.java | 4 +- .../reactive/accept/ContentTypeResolver.java | 7 ++-- .../accept/HeaderContentTypeResolver.java | 9 ++--- .../accept/ParameterContentTypeResolver.java | 6 +-- .../PathExtensionContentTypeResolver.java | 14 +++---- .../AbstractMediaTypeExpression.java | 11 ++++-- .../condition/ConsumesRequestCondition.java | 6 +-- .../condition/ProducesRequestCondition.java | 8 ++-- .../RequestMappingInfoHandlerMapping.java | 32 ++++++++------- .../annotation/ResponseBodyResultHandler.java | 6 +-- .../reactive/DispatcherHandlerErrorTests.java | 16 ++++---- .../ResponseStatusExceptionHandlerTests.java | 4 +- ...positeContentTypeResolverBuilderTests.java | 6 +-- .../HeaderContentTypeResolverTests.java | 4 +- ...athExtensionContentTypeResolverTests.java} | 6 +-- ...RequestMappingInfoHandlerMappingTests.java | 39 +++++++++---------- 18 files changed, 95 insertions(+), 125 deletions(-) delete mode 100644 spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerNotFoundException.java rename spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/{PathExtensionContentNegotiationStrategyTests.java => PathExtensionContentTypeResolverTests.java} (96%) diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerNotFoundException.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerNotFoundException.java deleted file mode 100644 index f9d8f074af6..00000000000 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/HandlerNotFoundException.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2002-2015 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.springframework.web.reactive; - -import org.springframework.core.NestedRuntimeException; - -/** - * @author Rossen Stoyanchev - */ -public class HandlerNotFoundException extends NestedRuntimeException { - - - public HandlerNotFoundException() { - super("No handler found."); - } - -} diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/AbstractMappingContentTypeResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/AbstractMappingContentTypeResolver.java index 3e89fe8a736..37f9f77d4a6 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/AbstractMappingContentTypeResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/AbstractMappingContentTypeResolver.java @@ -29,7 +29,7 @@ import org.springframework.http.MediaType; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.StringUtils; -import org.springframework.web.HttpMediaTypeNotAcceptableException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; /** @@ -85,7 +85,7 @@ public abstract class AbstractMappingContentTypeResolver implements MappingConte @Override public List resolveMediaTypes(ServerWebExchange exchange) - throws HttpMediaTypeNotAcceptableException { + throws NotAcceptableStatusException { String key = extractKey(exchange); return resolveMediaTypes(key); @@ -95,11 +95,9 @@ public abstract class AbstractMappingContentTypeResolver implements MappingConte * An overloaded resolve method with a pre-resolved lookup key. * @param key the key for looking up media types * @return a list of resolved media types or an empty list - * @throws HttpMediaTypeNotAcceptableException + * @throws NotAcceptableStatusException */ - public List resolveMediaTypes(String key) - throws HttpMediaTypeNotAcceptableException { - + public List resolveMediaTypes(String key) throws NotAcceptableStatusException { if (StringUtils.hasText(key)) { MediaType mediaType = getMediaType(key); if (mediaType != null) { @@ -139,7 +137,7 @@ public abstract class AbstractMappingContentTypeResolver implements MappingConte * this method it will be added to the mappings. */ @SuppressWarnings("UnusedParameters") - protected MediaType handleNoMatch(String key) throws HttpMediaTypeNotAcceptableException { + protected MediaType handleNoMatch(String key) throws NotAcceptableStatusException { return null; } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/CompositeContentTypeResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/CompositeContentTypeResolver.java index 71377ab377e..68df9065082 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/CompositeContentTypeResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/CompositeContentTypeResolver.java @@ -23,7 +23,7 @@ import java.util.Set; import org.springframework.http.MediaType; import org.springframework.util.Assert; -import org.springframework.web.HttpMediaTypeNotAcceptableException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; /** @@ -71,7 +71,7 @@ public class CompositeContentTypeResolver implements MappingContentTypeResolver @Override - public List resolveMediaTypes(ServerWebExchange exchange) throws HttpMediaTypeNotAcceptableException { + public List resolveMediaTypes(ServerWebExchange exchange) throws NotAcceptableStatusException { for (ContentTypeResolver resolver : this.resolvers) { List mediaTypes = resolver.resolveMediaTypes(exchange); if (mediaTypes.isEmpty() || (mediaTypes.size() == 1 && mediaTypes.contains(MediaType.ALL))) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/ContentTypeResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/ContentTypeResolver.java index c91c494a622..e359cdeed58 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/ContentTypeResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/ContentTypeResolver.java @@ -18,7 +18,7 @@ package org.springframework.web.reactive.accept; import java.util.List; import org.springframework.http.MediaType; -import org.springframework.web.HttpMediaTypeNotAcceptableException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; /** @@ -34,9 +34,8 @@ public interface ContentTypeResolver { * @param exchange the current exchange * @return the requested media types or an empty list * - * @throws HttpMediaTypeNotAcceptableException if the requested media - * types cannot be parsed + * @throws NotAcceptableStatusException if the requested media types is invalid */ - List resolveMediaTypes(ServerWebExchange exchange) throws HttpMediaTypeNotAcceptableException; + List resolveMediaTypes(ServerWebExchange exchange) throws NotAcceptableStatusException; } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/HeaderContentTypeResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/HeaderContentTypeResolver.java index de6caac1507..4ef573a93c2 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/HeaderContentTypeResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/HeaderContentTypeResolver.java @@ -19,7 +19,7 @@ import java.util.List; import org.springframework.http.InvalidMediaTypeException; import org.springframework.http.MediaType; -import org.springframework.web.HttpMediaTypeNotAcceptableException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; /** @@ -30,9 +30,7 @@ import org.springframework.web.server.ServerWebExchange; public class HeaderContentTypeResolver implements ContentTypeResolver { @Override - public List resolveMediaTypes(ServerWebExchange exchange) - throws HttpMediaTypeNotAcceptableException { - + public List resolveMediaTypes(ServerWebExchange exchange) throws NotAcceptableStatusException { try { List mediaTypes = exchange.getRequest().getHeaders().getAccept(); MediaType.sortBySpecificityAndQuality(mediaTypes); @@ -40,8 +38,9 @@ public class HeaderContentTypeResolver implements ContentTypeResolver { } catch (InvalidMediaTypeException ex) { String value = exchange.getRequest().getHeaders().getFirst("Accept"); - throw new HttpMediaTypeNotAcceptableException( + throw new NotAcceptableStatusException( "Could not parse 'Accept' header [" + value + "]: " + ex.getMessage()); } } + } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/ParameterContentTypeResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/ParameterContentTypeResolver.java index 4b6ed63678b..70641c3b451 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/ParameterContentTypeResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/ParameterContentTypeResolver.java @@ -23,7 +23,7 @@ import org.apache.commons.logging.LogFactory; import org.springframework.http.MediaType; import org.springframework.util.Assert; -import org.springframework.web.HttpMediaTypeNotAcceptableException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; /** @@ -75,8 +75,8 @@ public class ParameterContentTypeResolver extends AbstractMappingContentTypeReso } @Override - protected MediaType handleNoMatch(String key) throws HttpMediaTypeNotAcceptableException { - throw new HttpMediaTypeNotAcceptableException(getMediaTypes()); + protected MediaType handleNoMatch(String key) throws NotAcceptableStatusException { + throw new NotAcceptableStatusException(getMediaTypes()); } } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java index f8ea0747c8d..57b98d666f5 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolver.java @@ -31,8 +31,7 @@ import org.springframework.http.MediaType; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.StringUtils; -import org.springframework.web.HttpMediaTypeNotAcceptableException; -import org.springframework.web.accept.PathExtensionContentNegotiationStrategy; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.util.WebUtils; @@ -49,11 +48,10 @@ import org.springframework.web.util.WebUtils; */ public class PathExtensionContentTypeResolver extends AbstractMappingContentTypeResolver { - private static final Log logger = LogFactory.getLog(PathExtensionContentNegotiationStrategy.class); + private static final Log logger = LogFactory.getLog(PathExtensionContentTypeResolver.class); - private static final boolean JAF_PRESENT = ClassUtils.isPresent( - "javax.activation.FileTypeMap", - PathExtensionContentNegotiationStrategy.class.getClassLoader()); + private static final boolean JAF_PRESENT = ClassUtils.isPresent("javax.activation.FileTypeMap", + PathExtensionContentTypeResolver.class.getClassLoader()); private boolean useJaf = true; @@ -104,7 +102,7 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType } @Override - protected MediaType handleNoMatch(String key) throws HttpMediaTypeNotAcceptableException { + protected MediaType handleNoMatch(String key) throws NotAcceptableStatusException { if (this.useJaf && JAF_PRESENT) { MediaType mediaType = JafMediaTypeFactory.getMediaType("file." + key); if (mediaType != null && !MediaType.APPLICATION_OCTET_STREAM.equals(mediaType)) { @@ -112,7 +110,7 @@ public class PathExtensionContentTypeResolver extends AbstractMappingContentType } } if (!this.ignoreUnknownExtensions) { - throw new HttpMediaTypeNotAcceptableException(getMediaTypes()); + throw new NotAcceptableStatusException(getMediaTypes()); } return null; } diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/condition/AbstractMediaTypeExpression.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/condition/AbstractMediaTypeExpression.java index 8ae39742575..6f9b773574b 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/condition/AbstractMediaTypeExpression.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/condition/AbstractMediaTypeExpression.java @@ -20,9 +20,10 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.http.MediaType; -import org.springframework.web.HttpMediaTypeException; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.UnsupportedMediaTypeStatusException; /** * Supports media type expressions as described in: @@ -72,12 +73,16 @@ abstract class AbstractMediaTypeExpression implements Comparable getAcceptedMediaTypes(ServerWebExchange exchange) - throws HttpMediaTypeNotAcceptableException { + throws NotAcceptableStatusException { List mediaTypes = this.contentTypeResolver.resolveMediaTypes(exchange); return mediaTypes.isEmpty() ? Collections.singletonList(MediaType.ALL) : mediaTypes; @@ -306,7 +306,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition acceptedMediaTypes = getAcceptedMediaTypes(exchange); for (MediaType acceptedMediaType : acceptedMediaTypes) { if (getMediaType().isCompatibleWith(acceptedMediaType)) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java index 7e295494167..fb99f6dec12 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMapping.java @@ -36,16 +36,16 @@ import org.springframework.http.MediaType; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.util.CollectionUtils; import org.springframework.util.MultiValueMap; -import org.springframework.web.HttpMediaTypeNotAcceptableException; -import org.springframework.web.HttpMediaTypeNotSupportedException; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.UnsatisfiedServletRequestParameterException; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.method.HandlerMethod; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.result.condition.NameValueExpression; import org.springframework.web.reactive.result.condition.ParamsRequestCondition; +import org.springframework.web.server.BadRequestStatusException; +import org.springframework.web.server.MethodNotAllowedException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.UnsupportedMediaTypeStatusException; import org.springframework.web.util.WebUtils; /** @@ -166,10 +166,13 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe /** * Iterate all RequestMappingInfos once again, look if any match by URL at * least and raise exceptions accordingly. - * @throws HttpRequestMethodNotSupportedException if there are matches by URL - * but not by HTTP method - * @throws HttpMediaTypeNotAcceptableException if there are matches by URL - * but not by consumable/producible media types + * @throws MethodNotAllowedException for matches by URL but not by HTTP method + * @throws UnsupportedMediaTypeStatusException if there are matches by URL + * and HTTP method but not by consumable media types + * @throws NotAcceptableStatusException if there are matches by URL and HTTP + * method but not by producible media types + * @throws BadRequestStatusException if there are matches by URL and HTTP + * method but not by query parameter conditions */ @Override protected HandlerMethod handleNoMatch(Set requestMappingInfos, @@ -205,7 +208,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe return new HandlerMethod(handler, HTTP_OPTIONS_HANDLE_METHOD); } else if (!allowedMethods.isEmpty()) { - throw new HttpRequestMethodNotSupportedException(httpMethod.name(), allowedMethods); + throw new MethodNotAllowedException(httpMethod.name(), allowedMethods); } } @@ -230,12 +233,12 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe contentType = request.getHeaders().getContentType(); } catch (InvalidMediaTypeException ex) { - throw new HttpMediaTypeNotSupportedException(ex.getMessage()); + throw new UnsupportedMediaTypeStatusException(ex.getMessage()); } - throw new HttpMediaTypeNotSupportedException(contentType, new ArrayList<>(consumableMediaTypes)); + throw new UnsupportedMediaTypeStatusException(contentType, new ArrayList<>(consumableMediaTypes)); } else if (!producibleMediaTypes.isEmpty()) { - throw new HttpMediaTypeNotAcceptableException(new ArrayList<>(producibleMediaTypes)); + throw new NotAcceptableStatusException(new ArrayList<>(producibleMediaTypes)); } else { if (!CollectionUtils.isEmpty(paramConditions)) { @@ -243,7 +246,8 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe .collect(Collectors.toMap(Entry::getKey, entry -> entry.getValue().toArray(new String[entry.getValue().size()])) ); - throw new UnsatisfiedServletRequestParameterException(paramConditions, params); + throw new BadRequestStatusException("Unsatisfied query parameter conditions: " + + paramConditions + ", actual: " + params); } else { return null; @@ -308,7 +312,7 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe } private static Set initAllowedHttpMethods(Set declaredMethods) { - Set result = new LinkedHashSet(declaredMethods.size()); + Set result = new LinkedHashSet<>(declaredMethods.size()); if (declaredMethods.isEmpty()) { for (HttpMethod method : HttpMethod.values()) { if (!HttpMethod.TRACE.equals(method)) { diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java index e0b5c2fdb89..c69a315401e 100644 --- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java +++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/result/method/annotation/ResponseBodyResultHandler.java @@ -42,11 +42,11 @@ import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.util.Assert; import org.springframework.util.MimeType; -import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.method.HandlerMethod; import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.HandlerResultHandler; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; @@ -170,7 +170,7 @@ public class ResponseBodyResultHandler implements HandlerResultHandler, Ordered } } if (compatibleMediaTypes.isEmpty()) { - return Mono.error(new HttpMediaTypeNotAcceptableException(producibleMediaTypes)); + return Mono.error(new NotAcceptableStatusException(producibleMediaTypes)); } List mediaTypes = new ArrayList<>(compatibleMediaTypes); @@ -200,7 +200,7 @@ public class ResponseBodyResultHandler implements HandlerResultHandler, Ordered } } - return Mono.error(new HttpMediaTypeNotAcceptableException(this.allMediaTypes)); + return Mono.error(new NotAcceptableStatusException(this.allMediaTypes)); } private List getAcceptableMediaTypes(ServerHttpRequest request) { diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java index cd5dce7650a..91c91bc9aaa 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/DispatcherHandlerErrorTests.java @@ -41,14 +41,14 @@ import org.springframework.http.MediaType; import org.springframework.http.server.reactive.MockServerHttpRequest; import org.springframework.http.server.reactive.MockServerHttpResponse; import org.springframework.stereotype.Controller; -import org.springframework.web.HttpMediaTypeNotAcceptableException; -import org.springframework.web.server.ResponseStatusException; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerAdapter; import org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping; import org.springframework.web.reactive.result.method.annotation.ResponseBodyResultHandler; +import org.springframework.web.server.NotAcceptableStatusException; +import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebExceptionHandler; import org.springframework.web.server.WebFilter; @@ -60,7 +60,9 @@ import org.springframework.web.server.handler.FilteringWebHandler; import org.springframework.web.server.session.WebSessionManager; import static org.hamcrest.CoreMatchers.startsWith; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; import static org.mockito.Mockito.mock; /** @@ -109,8 +111,7 @@ public class DispatcherHandlerErrorTests { Throwable ex = awaitErrorSignal(publisher); assertEquals(ResponseStatusException.class, ex.getClass()); - assertNotNull(ex.getCause()); - assertEquals(HandlerNotFoundException.class, ex.getCause().getClass()); + assertEquals(HttpStatus.NOT_FOUND, ((ResponseStatusException) ex).getStatus()); } @Test @@ -166,9 +167,7 @@ public class DispatcherHandlerErrorTests { Mono publisher = this.dispatcherHandler.handle(this.exchange); Throwable ex = awaitErrorSignal(publisher); - assertEquals(ResponseStatusException.class, ex.getClass()); - assertNotNull(ex.getCause()); - assertEquals(HttpMediaTypeNotAcceptableException.class, ex.getCause().getClass()); + assertEquals(NotAcceptableStatusException.class, ex.getClass()); } @Test @@ -181,7 +180,6 @@ public class DispatcherHandlerErrorTests { ex.printStackTrace(); assertSame(EXCEPTION, ex); - } @Test diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/ResponseStatusExceptionHandlerTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/ResponseStatusExceptionHandlerTests.java index c5b85760a73..f36b67f2bba 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/ResponseStatusExceptionHandlerTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/ResponseStatusExceptionHandlerTests.java @@ -35,6 +35,8 @@ import static org.junit.Assert.*; import static org.mockito.Mockito.mock; /** + * Unit tests for {@link ResponseStatusExceptionHandler}. + * * @author Rossen Stoyanchev */ public class ResponseStatusExceptionHandlerTests { @@ -58,7 +60,7 @@ public class ResponseStatusExceptionHandlerTests { @Test public void handleException() throws Exception { - Throwable ex = new ResponseStatusException(HttpStatus.BAD_REQUEST); + Throwable ex = new ResponseStatusException(HttpStatus.BAD_REQUEST, ""); Mono publisher = this.handler.handle(this.exchange, ex); publisher.get(); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/CompositeContentTypeResolverBuilderTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/CompositeContentTypeResolverBuilderTests.java index 074dc914a7f..6295b997a26 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/CompositeContentTypeResolverBuilderTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/CompositeContentTypeResolverBuilderTests.java @@ -26,7 +26,7 @@ import org.springframework.http.MediaType; import org.springframework.http.server.reactive.MockServerHttpRequest; import org.springframework.http.server.reactive.MockServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.web.HttpMediaTypeNotAcceptableException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.WebSessionManager; @@ -102,7 +102,7 @@ public class CompositeContentTypeResolverBuilderTests { assertEquals(Collections.emptyList(), resolver.resolveMediaTypes(exchange)); } - @Test(expected = HttpMediaTypeNotAcceptableException.class) // SPR-10170 + @Test(expected = NotAcceptableStatusException.class) // SPR-10170 public void favorPathWithIgnoreUnknownPathExtensionTurnedOff() throws Exception { CompositeContentTypeResolver resolver = new CompositeContentTypeResolverBuilder() .favorPathExtension(true) @@ -129,7 +129,7 @@ public class CompositeContentTypeResolverBuilderTests { resolver.resolveMediaTypes(exchange)); } - @Test(expected = HttpMediaTypeNotAcceptableException.class) // SPR-10170 + @Test(expected = NotAcceptableStatusException.class) // SPR-10170 public void favorParameterWithUnknownMediaType() throws Exception { CompositeContentTypeResolver resolver = new CompositeContentTypeResolverBuilder() .favorParameter(true) diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/HeaderContentTypeResolverTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/HeaderContentTypeResolverTests.java index 9b2288b2c41..5280ed03932 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/HeaderContentTypeResolverTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/HeaderContentTypeResolverTests.java @@ -27,7 +27,7 @@ import org.springframework.http.MediaType; import org.springframework.http.server.reactive.MockServerHttpRequest; import org.springframework.http.server.reactive.MockServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.web.HttpMediaTypeNotAcceptableException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.WebSessionManager; @@ -63,7 +63,7 @@ public class HeaderContentTypeResolverTests { assertEquals("text/plain;q=0.5", mediaTypes.get(3).toString()); } - @Test(expected=HttpMediaTypeNotAcceptableException.class) + @Test(expected=NotAcceptableStatusException.class) public void resolveMediaTypesParseError() throws Exception { ServerWebExchange exchange = createExchange("textplain; q=0.5"); this.resolver.resolveMediaTypes(exchange); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/PathExtensionContentNegotiationStrategyTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolverTests.java similarity index 96% rename from spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/PathExtensionContentNegotiationStrategyTests.java rename to spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolverTests.java index 4399f7c56e7..db71fcf1c45 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/PathExtensionContentNegotiationStrategyTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/accept/PathExtensionContentTypeResolverTests.java @@ -28,7 +28,7 @@ import org.springframework.http.MediaType; import org.springframework.http.server.reactive.MockServerHttpRequest; import org.springframework.http.server.reactive.MockServerHttpResponse; import org.springframework.http.server.reactive.ServerHttpRequest; -import org.springframework.web.HttpMediaTypeNotAcceptableException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.WebSessionManager; @@ -41,7 +41,7 @@ import static org.mockito.Mockito.mock; * * @author Rossen Stoyanchev */ -public class PathExtensionContentNegotiationStrategyTests { +public class PathExtensionContentTypeResolverTests { @Test public void resolveMediaTypesFromMapping() throws Exception { @@ -101,7 +101,7 @@ public class PathExtensionContentNegotiationStrategyTests { assertEquals(Collections.emptyList(), mediaTypes); } - @Test(expected = HttpMediaTypeNotAcceptableException.class) + @Test(expected = NotAcceptableStatusException.class) public void resolveMediaTypesDoNotIgnoreUnknownExtension() throws Exception { ServerWebExchange exchange = createExchange("test.xyz"); PathExtensionContentTypeResolver resolver = new PathExtensionContentTypeResolver(); diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java index 50ca621bb41..7239f8ed8b0 100644 --- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java +++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/RequestMappingInfoHandlerMappingTests.java @@ -22,12 +22,12 @@ import java.net.URISyntaxException; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; +import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; import reactor.core.publisher.Mono; @@ -44,10 +44,6 @@ import org.springframework.stereotype.Controller; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.ModelMap; import org.springframework.util.MultiValueMap; -import org.springframework.web.HttpMediaTypeNotAcceptableException; -import org.springframework.web.HttpMediaTypeNotSupportedException; -import org.springframework.web.HttpRequestMethodNotSupportedException; -import org.springframework.web.bind.UnsatisfiedServletRequestParameterException; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @@ -55,17 +51,19 @@ import org.springframework.web.method.HandlerMethod; import org.springframework.web.reactive.HandlerMapping; import org.springframework.web.reactive.HandlerResult; import org.springframework.web.reactive.result.method.RequestMappingInfo.BuilderConfiguration; +import org.springframework.web.server.BadRequestStatusException; +import org.springframework.web.server.MethodNotAllowedException; +import org.springframework.web.server.NotAcceptableStatusException; import org.springframework.web.server.ServerWebExchange; +import org.springframework.web.server.UnsupportedMediaTypeStatusException; import org.springframework.web.server.adapter.DefaultServerWebExchange; import org.springframework.web.server.session.WebSessionManager; import org.springframework.web.util.HttpRequestPathHelper; -import static org.hamcrest.Matchers.containsInAnyOrder; -import static org.junit.Assert.assertArrayEquals; +import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; @@ -151,8 +149,8 @@ public class RequestMappingInfoHandlerMappingTests { public void getHandlerRequestMethodNotAllowed() throws Exception { ServerWebExchange exchange = createExchange(HttpMethod.POST, "/bar"); Mono mono = this.handlerMapping.getHandler(exchange); - assertError(mono, HttpRequestMethodNotSupportedException.class, - ex -> assertArrayEquals(new String[]{"GET", "HEAD"}, ex.getSupportedMethods())); + assertError(mono, MethodNotAllowedException.class, + ex -> assertEquals(new HashSet<>(Arrays.asList("GET", "HEAD")), ex.getSupportedMethods())); } // SPR-9603 @@ -166,7 +164,7 @@ public class RequestMappingInfoHandlerMappingTests { TestSubscriber subscriber = new TestSubscriber<>(); mono.subscribeWith(subscriber); - subscriber.assertError(HttpMediaTypeNotAcceptableException.class); + subscriber.assertError(NotAcceptableStatusException.class); } // SPR-8462 @@ -191,8 +189,10 @@ public class RequestMappingInfoHandlerMappingTests { ServerWebExchange exchange = createExchange(HttpMethod.PUT, "/person/1"); exchange.getRequest().getHeaders().add("Content-Type", "bogus"); Mono mono = this.handlerMapping.getHandler(exchange); - assertError(mono, HttpMediaTypeNotSupportedException.class, - ex -> assertEquals("Invalid mime type \"bogus\": does not contain '/'", ex.getMessage())); + assertError(mono, UnsupportedMediaTypeStatusException.class, + ex -> assertEquals("Request failure [status: 415, " + + "reason: \"Invalid mime type \"bogus\": does not contain '/'\"]", + ex.getMessage())); } // SPR-8462 @@ -210,11 +210,8 @@ public class RequestMappingInfoHandlerMappingTests { public void getHandlerUnsatisfiedServletRequestParameterException() throws Exception { ServerWebExchange exchange = createExchange(HttpMethod.GET, "/params"); Mono mono = this.handlerMapping.getHandler(exchange); - assertError(mono, UnsatisfiedServletRequestParameterException.class, ex -> { - List groups = ex.getParamConditionGroups(); - assertEquals(2, groups.size()); - assertThat(Arrays.asList("foo=bar", "bar=baz"), - containsInAnyOrder(groups.get(0)[0], groups.get(1)[0])); + assertError(mono, BadRequestStatusException.class, ex -> { + assertThat(ex.getReason(), Matchers.startsWith("Unsatisfied query parameter conditions:")); }); } @@ -380,10 +377,10 @@ public class RequestMappingInfoHandlerMappingTests { exchange.getRequest().getHeaders().setContentType(MediaType.APPLICATION_JSON); Mono mono = this.handlerMapping.getHandler(exchange); - assertError(mono, HttpMediaTypeNotSupportedException.class, ex -> + assertError(mono, UnsupportedMediaTypeStatusException.class, ex -> assertEquals("Invalid supported consumable media types", Collections.singletonList(new MediaType("application", "xml")), - ex.getSupportedMediaTypes())); + ex.getSupportedContentTypes())); } private void testHttpOptions(String requestURI, String allowHeader) throws Exception { @@ -407,7 +404,7 @@ public class RequestMappingInfoHandlerMappingTests { exchange.getRequest().getHeaders().setAccept(Collections.singletonList(MediaType.APPLICATION_JSON)); Mono mono = this.handlerMapping.getHandler(exchange); - assertError(mono, HttpMediaTypeNotAcceptableException.class, ex -> + assertError(mono, NotAcceptableStatusException.class, ex -> assertEquals("Invalid supported producible media types", Collections.singletonList(new MediaType("application", "xml")), ex.getSupportedMediaTypes()));