SPR-7353 - Added equivalent of JAX-RS @Produces to Spring MVC

This commit is contained in:
Arjen Poutsma
2011-05-13 09:43:45 +00:00
parent a557878a6f
commit bb2cc8457f
11 changed files with 702 additions and 131 deletions

View File

@@ -21,7 +21,6 @@ import java.util.Comparator;
import java.util.List;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
@@ -100,7 +99,7 @@ public class RequestMappingInfoComparatorTests {
RequestMappingInfo empty = new RequestMappingInfo(null, null);
RequestMappingInfo oneMethod = new RequestMappingInfo(null, new RequestMethod[] {RequestMethod.GET});
RequestMappingInfo oneMethodOneParam =
new RequestMappingInfo(null, RequestConditionFactory.parseMethods(RequestMethod.GET), RequestConditionFactory.parseParams("foo"), null, null);
new RequestMappingInfo(null, RequestConditionFactory.parseMethods(RequestMethod.GET), RequestConditionFactory.parseParams("foo"), null, null, null);
List<RequestMappingInfo> list = asList(empty, oneMethod, oneMethodOneParam);
Collections.shuffle(list);
Collections.sort(list, handlerMapping.getMappingComparator("", request));
@@ -111,16 +110,16 @@ public class RequestMappingInfoComparatorTests {
}
@Test
@Ignore // TODO : remove ignore
public void acceptHeaders() {
RequestMappingInfo html = new RequestMappingInfo(null, null, null, RequestConditionFactory.parseHeaders("accept=text/html"), null);
RequestMappingInfo xml = new RequestMappingInfo(null, null, null, RequestConditionFactory.parseHeaders("accept=application/xml"), null);
public void produces() {
RequestMappingInfo html = new RequestMappingInfo(null, null, null, null, null, RequestConditionFactory.parseProduces("text/html"));
RequestMappingInfo xml = new RequestMappingInfo(null, null, null, null, null, RequestConditionFactory.parseProduces("application/xml"));
RequestMappingInfo none = new RequestMappingInfo(null, null);
request.addHeader("Accept", "application/xml, text/html");
Comparator<RequestMappingInfo> comparator = handlerMapping.getMappingComparator("", request);
assertTrue(comparator.compare(html, xml) > 0);
int result = comparator.compare(html, xml);
assertTrue("Invalid comparison result: " + result, result > 0);
assertTrue(comparator.compare(xml, html) < 0);
assertTrue(comparator.compare(xml, none) < 0);
assertTrue(comparator.compare(none, xml) > 0);

View File

@@ -181,13 +181,13 @@ public class RequestMappingInfoTests {
RequestMappingInfo key =
new RequestMappingInfo(asList("/foo"), null, RequestConditionFactory.parseParams("foo=bar"), null,
null);
null, null);
RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNotNull(match);
key = new RequestMappingInfo(singleton("/foo"), null, RequestConditionFactory.parseParams("foo!=bar"), null,
null);
null, null);
match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNull(match);
@@ -202,13 +202,13 @@ public class RequestMappingInfoTests {
RequestMappingInfo key =
new RequestMappingInfo(singleton("/foo"), null, null, RequestConditionFactory.parseHeaders("foo=bar"),
null);
null, null);
RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNotNull(match);
key = new RequestMappingInfo(singleton("/foo"), null, null, RequestConditionFactory.parseHeaders("foo!=bar"),
null);
null, null);
match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNull(match);
@@ -222,13 +222,33 @@ public class RequestMappingInfoTests {
String lookupPath = new UrlPathHelper().getLookupPathForRequest(request);
RequestMappingInfo key = new RequestMappingInfo(singleton("/foo"), null, null, null,
RequestConditionFactory.parseConsumes("text/plain"));
RequestConditionFactory.parseConsumes("text/plain"), null);
RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNotNull(match);
key = new RequestMappingInfo(singleton("/foo"), null, null, null,
RequestConditionFactory.parseConsumes("application/xml"));
RequestConditionFactory.parseConsumes("application/xml"), null);
match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNull(match);
}
@Test
public void producesCondition() {
PathMatcher pathMatcher = new AntPathMatcher();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo");
request.addHeader("Accept", "text/plain");
String lookupPath = new UrlPathHelper().getLookupPathForRequest(request);
RequestMappingInfo key = new RequestMappingInfo(singleton("/foo"), null, null, null,
null, RequestConditionFactory.parseProduces("text/plain"));
RequestMappingInfo match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNotNull(match);
key = new RequestMappingInfo(singleton("/foo"), null, null, null, null,
RequestConditionFactory.parseProduces("application/xml"));
match = key.getMatchingRequestMapping(lookupPath, request, pathMatcher);
assertNull(match);

View File

@@ -16,14 +16,6 @@
package org.springframework.web.servlet.mvc.method.annotation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.beans.PropertyEditorSupport;
import java.io.IOException;
import java.io.Serializable;
@@ -48,7 +40,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
@@ -60,8 +51,8 @@ import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.xml.bind.annotation.XmlRootElement;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.aop.interceptor.SimpleTraceInterceptor;
import org.springframework.aop.support.DefaultPointcutAdvisor;
@@ -142,6 +133,8 @@ import org.springframework.web.servlet.mvc.method.annotation.support.ServletWebA
import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import static org.junit.Assert.*;
/**
* The origin of this test fixture is {@link ServletHandlerMethodTests} with tests in this class adapted to run
* against the HandlerMethod infrastructure rather than against the DefaultAnnotationHandlerMapping, the
@@ -1033,8 +1026,6 @@ public class ServletHandlerMethodTests {
assertEquals("non-pdf", response.getContentAsString());
}
// TODO: uncomment ignore
@Ignore
@Test
public void acceptHeaders() throws ServletException, IOException {
initDispatcherServlet(AcceptHeadersController.class, null);

View File

@@ -0,0 +1,232 @@
/*
* Copyright 2002-2011 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.servlet.mvc.method.condition;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.junit.Test;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockHttpServletRequest;
import static org.junit.Assert.*;
/**
* @author Arjen Poutsma
*/
public class ProducesRequestConditionTests {
@Test
public void consumesMatch() {
RequestCondition condition = new ProducesRequestCondition("text/plain");
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Accept", "text/plain");
assertTrue(condition.match(request));
}
@Test
public void negatedConsumesMatch() {
RequestCondition condition = new ProducesRequestCondition("!text/plain");
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Accept", "text/plain");
assertFalse(condition.match(request));
}
@Test
public void consumesWildcardMatch() {
RequestCondition condition = new ProducesRequestCondition("text/*");
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Accept", "text/plain");
assertTrue(condition.match(request));
}
@Test
public void consumesMultipleMatch() {
RequestCondition condition = new ProducesRequestCondition("text/plain", "application/xml");
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Accept", "text/plain");
assertTrue(condition.match(request));
}
@Test
public void consumesSingleNoMatch() {
RequestCondition condition = new ProducesRequestCondition("text/plain");
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Accept", "application/xml");
assertFalse(condition.match(request));
}
@Test
public void compareToSingle() {
ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain");
ProducesRequestCondition condition2 = new ProducesRequestCondition("text/*");
List<MediaType> accept = Collections.singletonList(MediaType.TEXT_PLAIN);
int result = condition1.compareTo(condition2, accept);
assertTrue("Invalid comparison result: " + result, result < 0);
result = condition2.compareTo(condition1, accept);
assertTrue("Invalid comparison result: " + result, result > 0);
}
@Test
public void compareToMultiple() {
ProducesRequestCondition condition1 = new ProducesRequestCondition("*/*", "text/plain");
ProducesRequestCondition condition2 = new ProducesRequestCondition("text/*", "text/plain;q=0.7");
List<MediaType> accept = Collections.singletonList(MediaType.TEXT_PLAIN);
int result = condition1.compareTo(condition2, accept);
assertTrue("Invalid comparison result: " + result, result < 0);
result = condition2.compareTo(condition1, accept);
assertTrue("Invalid comparison result: " + result, result > 0);
condition1 = new ProducesRequestCondition("*/*");
condition2 = new ProducesRequestCondition("text/*");
accept = Collections.singletonList(new MediaType("text", "*"));
result = condition1.compareTo(condition2, accept);
assertTrue("Invalid comparison result: " + result, result > 0);
result = condition2.compareTo(condition1, accept);
assertTrue("Invalid comparison result: " + result, result < 0);
}
@Test
public void compareToMultipleAccept() {
ProducesRequestCondition condition1 = new ProducesRequestCondition("text/*", "text/plain");
ProducesRequestCondition condition2 = new ProducesRequestCondition("application/*", "application/xml");
List<MediaType> accept = Arrays.asList(MediaType.TEXT_PLAIN, MediaType.APPLICATION_XML);
int result = condition1.compareTo(condition2, accept);
assertTrue("Invalid comparison result: " + result, result < 0);
result = condition2.compareTo(condition1, accept);
assertTrue("Invalid comparison result: " + result, result > 0);
accept = Arrays.asList(MediaType.APPLICATION_XML, MediaType.TEXT_PLAIN);
result = condition1.compareTo(condition2, accept);
assertTrue("Invalid comparison result: " + result, result > 0);
result = condition2.compareTo(condition1, accept);
assertTrue("Invalid comparison result: " + result, result < 0);
}
@Test
public void combine() {
ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain");
ProducesRequestCondition condition2 = new ProducesRequestCondition("application/xml");
ProducesRequestCondition result = condition1.combine(condition2);
assertEquals(condition2, result);
}
@Test
public void combineWithDefault() {
ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain");
ProducesRequestCondition condition2 = new ProducesRequestCondition("*/*");
ProducesRequestCondition result = condition1.combine(condition2);
assertEquals(condition1, result);
}
@Test
public void parseConsumesAndHeaders() {
String[] consumes = new String[] {"text/plain"};
String[] headers = new String[]{"foo=bar", "accept=application/xml,application/pdf"};
ProducesRequestCondition condition = RequestConditionFactory.parseProduces(consumes, headers);
assertConditions(condition, "text/plain", "application/xml", "application/pdf");
}
@Test
public void parseConsumesDefault() {
String[] consumes = new String[] {"*/*"};
String[] headers = new String[0];
ProducesRequestCondition condition = RequestConditionFactory.parseProduces(consumes, headers);
assertConditions(condition, "*/*");
}
@Test
public void parseConsumesDefaultAndHeaders() {
String[] consumes = new String[] {"*/*"};
String[] headers = new String[]{"foo=bar", "accept=text/plain"};
ProducesRequestCondition condition = RequestConditionFactory.parseProduces(consumes, headers);
assertConditions(condition, "text/plain");
}
@Test
public void getMatchingCondition() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.addHeader("Accept", "text/plain");
ProducesRequestCondition condition = new ProducesRequestCondition("text/plain", "application/xml");
ProducesRequestCondition result = condition.getMatchingCondition(request);
assertConditions(result, "text/plain");
condition = new ProducesRequestCondition("application/xml");
result = condition.getMatchingCondition(request);
assertNull(result);
}
private void assertConditions(ProducesRequestCondition condition, String... expected) {
Set<ProducesRequestCondition.ProduceRequestCondition> conditions = condition.getConditions();
assertEquals("Invalid amount of conditions", conditions.size(), expected.length);
for (String s : expected) {
boolean found = false;
for (ProducesRequestCondition.ProduceRequestCondition requestCondition : conditions) {
String conditionMediaType = requestCondition.getMediaType().toString();
if (conditionMediaType.equals(s)) {
found = true;
break;
}
}
if (!found) {
fail("Condition [" + s + "] not found");
}
}
}
}