From 281b243b88cccb45e55c7d1a168dde59819d6ac4 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 24 Sep 2014 17:56:07 +0200 Subject: [PATCH] HttpEntityMethodProcessor supports custom HttpEntity subclasses again Issue: SPR-12242 --- .../annotation/HttpEntityMethodProcessor.java | 8 ++-- .../HttpEntityMethodProcessorMockTests.java | 33 +++++++------ .../HttpEntityMethodProcessorTests.java | 48 ++++++++++++------- 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java index ec799a96c6..689ee869d6 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessor.java @@ -67,7 +67,7 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro } - @Override + @Override public boolean supportsParameter(MethodParameter parameter) { return HttpEntity.class.equals(parameter.getParameterType()) || RequestEntity.class.equals(parameter.getParameterType()); @@ -75,8 +75,8 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro @Override public boolean supportsReturnType(MethodParameter returnType) { - return HttpEntity.class.equals(returnType.getParameterType()) || - ResponseEntity.class.equals(returnType.getParameterType()); + return HttpEntity.class.isAssignableFrom(returnType.getParameterType()) && + !RequestEntity.class.isAssignableFrom(returnType.getParameterType()); } @Override @@ -94,7 +94,6 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro } else { return new HttpEntity(body, inputMessage.getHeaders()); - } } @@ -152,4 +151,5 @@ public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodPro return ResolvableType.forMethodParameter(returnType, type).resolve(Object.class); } } + } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java index 163649f02f..a1c6c928ae 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorMockTests.java @@ -20,11 +20,11 @@ import java.lang.reflect.Method; import java.net.URI; import java.util.Arrays; import java.util.Collections; -import java.util.List; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; + import org.springframework.core.MethodParameter; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -41,7 +41,6 @@ import org.springframework.mock.web.test.MockHttpServletResponse; import org.springframework.web.HttpMediaTypeNotAcceptableException; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.support.ModelAndViewContainer; @@ -66,21 +65,22 @@ public class HttpEntityMethodProcessorMockTests { private HttpMessageConverter messageConverter; private MethodParameter paramHttpEntity; + private MethodParameter paramRequestEntity; private MethodParameter paramResponseEntity; private MethodParameter paramInt; private MethodParameter returnTypeResponseEntity; - private MethodParameter returnTypeHttpEntity; - private MethodParameter returnTypeInt; - private MethodParameter paramRequestEntity; private MethodParameter returnTypeResponseEntityProduces; + private MethodParameter returnTypeHttpEntity; + private MethodParameter returnTypeHttpEntitySubclass; + private MethodParameter returnTypeInt; private ModelAndViewContainer mavContainer; - private ServletWebRequest webRequest; + private MockHttpServletRequest servletRequest; private MockHttpServletResponse servletResponse; - private MockHttpServletRequest servletRequest; + private ServletWebRequest webRequest; @SuppressWarnings("unchecked") @@ -92,27 +92,24 @@ public class HttpEntityMethodProcessorMockTests { processor = new HttpEntityMethodProcessor(Collections.>singletonList(messageConverter)); reset(messageConverter); - Method handle1 = getClass().getMethod("handle1", HttpEntity.class, ResponseEntity.class, Integer.TYPE, RequestEntity.class); paramHttpEntity = new MethodParameter(handle1, 0); + paramRequestEntity = new MethodParameter(handle1, 3); paramResponseEntity = new MethodParameter(handle1, 1); paramInt = new MethodParameter(handle1, 2); - paramRequestEntity = new MethodParameter(handle1, 3); returnTypeResponseEntity = new MethodParameter(handle1, -1); - + returnTypeResponseEntityProduces = new MethodParameter(getClass().getMethod("handle4"), -1); returnTypeHttpEntity = new MethodParameter(getClass().getMethod("handle2", HttpEntity.class), -1); - + returnTypeHttpEntitySubclass = new MethodParameter(getClass().getMethod("handle2x", HttpEntity.class), -1); returnTypeInt = new MethodParameter(getClass().getMethod("handle3"), -1); - returnTypeResponseEntityProduces = new MethodParameter(getClass().getMethod("handle4"), -1); - mavContainer = new ModelAndViewContainer(); - servletRequest = new MockHttpServletRequest(); servletResponse = new MockHttpServletResponse(); webRequest = new ServletWebRequest(servletRequest, servletResponse); } + @Test public void supportsParameter() { assertTrue("HttpEntity parameter not supported", processor.supportsParameter(paramHttpEntity)); @@ -125,6 +122,7 @@ public class HttpEntityMethodProcessorMockTests { public void supportsReturnType() { assertTrue("ResponseEntity return type not supported", processor.supportsReturnType(returnTypeResponseEntity)); assertTrue("HttpEntity return type not supported", processor.supportsReturnType(returnTypeHttpEntity)); + assertTrue("Custom HttpEntity subclass not supported", processor.supportsReturnType(returnTypeHttpEntitySubclass)); assertFalse("RequestEntity parameter supported", processor.supportsReturnType(paramRequestEntity)); assertFalse("non-ResponseBody return type supported", processor.supportsReturnType(returnTypeInt)); @@ -328,6 +326,10 @@ public class HttpEntityMethodProcessorMockTests { return entity; } + public CustomHttpEntity handle2x(HttpEntity entity) { + return new CustomHttpEntity(); + } + public int handle3() { return 42; } @@ -338,4 +340,7 @@ public class HttpEntityMethodProcessorMockTests { } + public static class CustomHttpEntity extends HttpEntity { + } + } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorTests.java index 23aa78c54c..4be8fda147 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/HttpEntityMethodProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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. @@ -15,8 +15,6 @@ */ package org.springframework.web.servlet.mvc.method.annotation; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; import java.io.Serializable; import java.lang.reflect.Method; @@ -25,6 +23,7 @@ import java.util.List; import org.junit.Before; import org.junit.Test; + import org.springframework.core.MethodParameter; import org.springframework.http.HttpEntity; import org.springframework.http.MediaType; @@ -40,6 +39,8 @@ import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.support.ModelAndViewContainer; +import static org.junit.Assert.*; + /** * Test fixture with {@link HttpEntityMethodProcessor} delegating to * actual {@link HttpMessageConverter} instances. @@ -51,32 +52,31 @@ import org.springframework.web.method.support.ModelAndViewContainer; public class HttpEntityMethodProcessorTests { private MethodParameter paramList; + private MethodParameter paramSimpleBean; private ModelAndViewContainer mavContainer; - private ServletWebRequest webRequest; - - private MockHttpServletResponse servletResponse; + private WebDataBinderFactory binderFactory; private MockHttpServletRequest servletRequest; - private WebDataBinderFactory binderFactory; + private MockHttpServletResponse servletResponse; + + private ServletWebRequest webRequest; + @Before public void setUp() throws Exception { - Method method = getClass().getMethod("handle", HttpEntity.class, HttpEntity.class); paramList = new MethodParameter(method, 0); paramSimpleBean = new MethodParameter(method, 1); mavContainer = new ModelAndViewContainer(); - + binderFactory = new ValidatingBinderFactory(); servletRequest = new MockHttpServletRequest(); servletResponse = new MockHttpServletResponse(); webRequest = new ServletWebRequest(servletRequest, servletResponse); - - binderFactory = new ValidatingBinderFactory(); } @Test @@ -118,7 +118,6 @@ public class HttpEntityMethodProcessorTests { @Test public void resolveArgumentTypeVariable() throws Exception { - Method method = MySimpleParameterizedController.class.getMethod("handleDto", HttpEntity.class); HandlerMethod handlerMethod = new HandlerMethod(new MySimpleParameterizedController(), method); MethodParameter methodParam = handlerMethod.getMethodParameters()[0]; @@ -132,31 +131,42 @@ public class HttpEntityMethodProcessorTests { HttpEntityMethodProcessor processor = new HttpEntityMethodProcessor(converters); @SuppressWarnings("unchecked") - HttpEntity result = (HttpEntity) processor.resolveArgument(methodParam, mavContainer, webRequest, binderFactory); + HttpEntity result = (HttpEntity) + processor.resolveArgument(methodParam, mavContainer, webRequest, binderFactory); assertNotNull(result); assertEquals("Jad", result.getBody().getName()); } + public void handle(HttpEntity> arg1, HttpEntity arg2) { } + private static abstract class MyParameterizedController { - @SuppressWarnings("unused") - public void handleDto(HttpEntity dto) {} + + public void handleDto(HttpEntity dto) { + } + } + + + private static class MySimpleParameterizedController extends MyParameterizedController { } - private static class MySimpleParameterizedController extends MyParameterizedController { } private interface Identifiable extends Serializable { + public Long getId(); + public void setId(Long id); } + @SuppressWarnings({ "serial" }) private static class SimpleBean implements Identifiable { private Long id; + private String name; @Override @@ -179,9 +189,11 @@ public class HttpEntityMethodProcessorTests { } } + private final class ValidatingBinderFactory implements WebDataBinderFactory { + @Override - public WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName) throws Exception { + public WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName) { LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean(); validator.afterPropertiesSet(); WebDataBinder dataBinder = new WebDataBinder(target, objectName); @@ -190,4 +202,4 @@ public class HttpEntityMethodProcessorTests { } } -} \ No newline at end of file +}