/** * Return the media types supported by all provided message converters sorted * by specificity via {@link MediaType#sortBySpecificity(List)}. */ private static List<MediaType> getAllSupportedMediaTypes(List<HttpMessageConverter<?>> messageConverters) { Set<MediaType> allSupportedMediaTypes = new LinkedHashSet<>(); for (HttpMessageConverter<?> messageConverter : messageConverters) { allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes()); } List<MediaType> result = new ArrayList<>(allSupportedMediaTypes); MediaType.sortBySpecificity(result); return Collections.unmodifiableList(result); }
if (converter instanceof GenericHttpMessageConverter && targetType != null) { if (((GenericHttpMessageConverter<?>) converter).canWrite(targetType, valueClass, null)) { result.addAll(converter.getSupportedMediaTypes()); result.addAll(converter.getSupportedMediaTypes());
private Stream<MediaType> getSupportedMediaTypes(HttpMessageConverter<?> messageConverter) { return messageConverter.getSupportedMediaTypes() .stream() .map(mediaType -> { if (mediaType.getCharset() != null) { return new MediaType(mediaType.getType(), mediaType.getSubtype()); } return mediaType; }); } }
@Before @SuppressWarnings("unchecked") public void setup() throws Exception { stringMessageConverter = mock(HttpMessageConverter.class); given(stringMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN)); resourceMessageConverter = mock(HttpMessageConverter.class); given(resourceMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.ALL)); resourceRegionMessageConverter = mock(HttpMessageConverter.class); given(resourceRegionMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.ALL)); processor = new RequestResponseBodyMethodProcessor( Arrays.asList(stringMessageConverter, resourceMessageConverter, resourceRegionMessageConverter)); mavContainer = new ModelAndViewContainer(); servletRequest = new MockHttpServletRequest(); servletRequest.setMethod("POST"); servletResponse = new MockHttpServletResponse(); webRequest = new ServletWebRequest(servletRequest, servletResponse); Method methodHandle1 = getClass().getMethod("handle1", String.class, Integer.TYPE); paramRequestBodyString = new MethodParameter(methodHandle1, 0); paramInt = new MethodParameter(methodHandle1, 1); paramValidBean = new MethodParameter(getClass().getMethod("handle2", SimpleBean.class), 0); paramStringNotRequired = new MethodParameter(getClass().getMethod("handle3", String.class), 0); paramOptionalString = new MethodParameter(getClass().getMethod("handle4", Optional.class), 0); returnTypeString = new MethodParameter(methodHandle1, -1); returnTypeInt = new MethodParameter(getClass().getMethod("handle5"), -1); returnTypeStringProduces = new MethodParameter(getClass().getMethod("handle6"), -1); returnTypeResource = new MethodParameter(getClass().getMethod("handle7"), -1); }
given(stringHttpMessageConverter.getSupportedMediaTypes()) .willReturn(Collections.singletonList(TEXT_PLAIN)); given(resourceMessageConverter.getSupportedMediaTypes()) .willReturn(Collections.singletonList(MediaType.ALL)); given(resourceRegionMessageConverter.getSupportedMediaTypes()) .willReturn(Collections.singletonList(MediaType.ALL));
private void initStringMessageConversion(MediaType accepted) { given(stringHttpMessageConverter.canWrite(String.class, null)).willReturn(true); given(stringHttpMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(TEXT_PLAIN)); given(stringHttpMessageConverter.canWrite(String.class, accepted)).willReturn(true); }
@Test public void shouldFailHandlingWhenContentTypeNotSupported() throws Exception { String body = "Foo"; ResponseEntity<String> returnValue = new ResponseEntity<>(body, HttpStatus.OK); MediaType accepted = MediaType.APPLICATION_ATOM_XML; servletRequest.addHeader("Accept", accepted.toString()); given(stringHttpMessageConverter.canWrite(String.class, null)).willReturn(true); given(stringHttpMessageConverter.getSupportedMediaTypes()) .willReturn(Collections.singletonList(TEXT_PLAIN)); this.thrown.expect(HttpMediaTypeNotAcceptableException.class); processor.handleReturnValue(returnValue, returnTypeResponseEntity, mavContainer, webRequest); }
@Test public void requestAvoidsDuplicateAcceptHeaderValues() throws Exception { HttpMessageConverter firstConverter = mock(HttpMessageConverter.class); given(firstConverter.canRead(any(), any())).willReturn(true); given(firstConverter.getSupportedMediaTypes()) .willReturn(Collections.singletonList(MediaType.TEXT_PLAIN)); HttpMessageConverter secondConverter = mock(HttpMessageConverter.class); given(secondConverter.canRead(any(), any())).willReturn(true); given(secondConverter.getSupportedMediaTypes()) .willReturn(Collections.singletonList(MediaType.TEXT_PLAIN)); HttpHeaders requestHeaders = new HttpHeaders(); mockSentRequest(GET, "http://example.com/", requestHeaders); mockResponseStatus(HttpStatus.OK); mockTextResponseBody("Hello World"); template.setMessageConverters(Arrays.asList(firstConverter, secondConverter)); template.getForObject("http://example.com/", String.class); assertEquals("Sent duplicate Accept header values", 1, requestHeaders.getAccept().size()); }
private void testResolveArgumentWithValidation(SimpleBean simpleBean) throws Exception { MediaType contentType = MediaType.TEXT_PLAIN; servletRequest.addHeader("Content-Type", contentType.toString()); servletRequest.setContent("payload".getBytes(StandardCharsets.UTF_8)); @SuppressWarnings("unchecked") HttpMessageConverter<SimpleBean> beanConverter = mock(HttpMessageConverter.class); given(beanConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN)); given(beanConverter.canRead(SimpleBean.class, contentType)).willReturn(true); given(beanConverter.read(eq(SimpleBean.class), isA(HttpInputMessage.class))).willReturn(simpleBean); processor = new RequestResponseBodyMethodProcessor(Collections.singletonList(beanConverter)); processor.resolveArgument(paramValidBean, mavContainer, webRequest, new ValidatingBinderFactory()); }
@Test public void shouldFailHandlingWhenConverterCannotWrite() throws Exception { String body = "Foo"; ResponseEntity<String> returnValue = new ResponseEntity<>(body, HttpStatus.OK); MediaType accepted = TEXT_PLAIN; servletRequest.addHeader("Accept", accepted.toString()); given(stringHttpMessageConverter.canWrite(String.class, null)).willReturn(true); given(stringHttpMessageConverter.getSupportedMediaTypes()) .willReturn(Collections.singletonList(TEXT_PLAIN)); given(stringHttpMessageConverter.canWrite(String.class, accepted)).willReturn(false); this.thrown.expect(HttpMediaTypeNotAcceptableException.class); processor.handleReturnValue(returnValue, returnTypeResponseEntityProduces, mavContainer, webRequest); }
@Test public void shouldFailResolvingWhenConverterCannotRead() throws Exception { MediaType contentType = TEXT_PLAIN; servletRequest.setMethod("POST"); servletRequest.addHeader("Content-Type", contentType.toString()); given(stringHttpMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(contentType)); given(stringHttpMessageConverter.canRead(String.class, contentType)).willReturn(false); this.thrown.expect(HttpMediaTypeNotSupportedException.class); processor.resolveArgument(paramHttpEntity, mavContainer, webRequest, null); }
@Test // SPR-15900 public void ioExceptionWithEmptyQueryString() throws Exception { // http://example.com/resource? URI uri = new URI("http", "example.com", "/resource", "", null); given(converter.canRead(String.class, null)).willReturn(true); given(converter.getSupportedMediaTypes()).willReturn(Collections.singletonList(parseMediaType("foo/bar"))); given(requestFactory.createRequest(uri, GET)).willReturn(request); given(request.getHeaders()).willReturn(new HttpHeaders()); given(request.execute()).willThrow(new IOException("Socket failure")); try { template.getForObject(uri, String.class); fail("RestClientException expected"); } catch (ResourceAccessException ex) { assertEquals("I/O error on GET request for \"http://example.com/resource\": " + "Socket failure; nested exception is java.io.IOException: Socket failure", ex.getMessage()); } }
@Test(expected = HttpMediaTypeNotAcceptableException.class) public void handleReturnValueNotAcceptableProduces() throws Exception { MediaType accepted = MediaType.TEXT_PLAIN; servletRequest.addHeader("Accept", accepted.toString()); given(stringMessageConverter.canWrite(String.class, null)).willReturn(true); given(stringMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN)); given(stringMessageConverter.canWrite(String.class, accepted)).willReturn(false); processor.handleReturnValue("Foo", returnTypeStringProduces, mavContainer, webRequest); }
@Test(expected = HttpMediaTypeNotAcceptableException.class) public void handleReturnValueNotAcceptable() throws Exception { MediaType accepted = MediaType.APPLICATION_ATOM_XML; servletRequest.addHeader("Accept", accepted.toString()); given(stringMessageConverter.canWrite(String.class, null)).willReturn(true); given(stringMessageConverter.getSupportedMediaTypes()).willReturn(Arrays.asList(MediaType.TEXT_PLAIN)); given(stringMessageConverter.canWrite(String.class, accepted)).willReturn(false); processor.handleReturnValue("Foo", returnTypeString, mavContainer, webRequest); }
@Test public void shouldHandleResource() throws Exception { ResponseEntity<Resource> returnValue = ResponseEntity .ok(new ByteArrayResource("Content".getBytes(StandardCharsets.UTF_8))); given(resourceMessageConverter.canWrite(ByteArrayResource.class, null)).willReturn(true); given(resourceMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.ALL)); given(resourceMessageConverter.canWrite(ByteArrayResource.class, APPLICATION_OCTET_STREAM)).willReturn(true); processor.handleReturnValue(returnValue, returnTypeResponseEntityResource, mavContainer, webRequest); then(resourceMessageConverter).should(times(1)).write( any(ByteArrayResource.class), eq(APPLICATION_OCTET_STREAM), any(HttpOutputMessage.class)); assertEquals(200, servletResponse.getStatus()); }
@Test public void handleReturnTypeResource() throws Exception { Resource returnValue = new ByteArrayResource("Content".getBytes(StandardCharsets.UTF_8)); given(resourceMessageConverter.canWrite(ByteArrayResource.class, null)).willReturn(true); given(resourceMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.ALL)); given(resourceMessageConverter.canWrite(ByteArrayResource.class, MediaType.APPLICATION_OCTET_STREAM)) .willReturn(true); processor.handleReturnValue(returnValue, returnTypeResource, mavContainer, webRequest); then(resourceMessageConverter).should(times(1)).write(any(ByteArrayResource.class), eq(MediaType.APPLICATION_OCTET_STREAM), any(HttpOutputMessage.class)); assertEquals(200, servletResponse.getStatus()); }
private void mockHttpMessageConverter(MediaType mediaType, Class type) { given(converter.canRead(type, null)).willReturn(true); given(converter.canRead(type, mediaType)).willReturn(true); given(converter.getSupportedMediaTypes()) .willReturn(Collections.singletonList(mediaType)); given(converter.canRead(type, mediaType)).willReturn(true); given(converter.canWrite(type, null)).willReturn(true); given(converter.canWrite(type, mediaType)).willReturn(true); }
@Test public void getUnsupportedMediaType() throws Exception { mockSentRequest(GET, "http://example.com/resource"); mockResponseStatus(HttpStatus.OK); given(converter.canRead(String.class, null)).willReturn(true); MediaType supportedMediaType = new MediaType("foo", "bar"); given(converter.getSupportedMediaTypes()).willReturn(Collections.singletonList(supportedMediaType)); MediaType barBaz = new MediaType("bar", "baz"); mockResponseBody("Foo", new MediaType("bar", "baz")); given(converter.canRead(String.class, barBaz)).willReturn(false); try { template.getForObject("http://example.com/{p}", String.class, "resource"); fail("UnsupportedMediaTypeException expected"); } catch (RestClientException ex) { // expected } verify(response).close(); }
@Test public void handleReturnValue() throws Exception { MediaType accepted = MediaType.TEXT_PLAIN; servletRequest.addHeader("Accept", accepted.toString()); String body = "Foo"; given(stringMessageConverter.canWrite(String.class, null)).willReturn(true); given(stringMessageConverter.getSupportedMediaTypes()).willReturn(Collections.singletonList(MediaType.TEXT_PLAIN)); given(stringMessageConverter.canWrite(String.class, accepted)).willReturn(true); processor.handleReturnValue(body, returnTypeString, mavContainer, webRequest); assertTrue("The requestHandled flag wasn't set", mavContainer.isRequestHandled()); verify(stringMessageConverter).write(eq(body), eq(accepted), isA(HttpOutputMessage.class)); }
@Test // SPR-9841 public void handleReturnValueMediaTypeSuffix() throws Exception { String body = "Foo"; MediaType accepted = MediaType.APPLICATION_XHTML_XML; List<MediaType> supported = Collections.singletonList(MediaType.valueOf("application/*+xml")); servletRequest.addHeader("Accept", accepted); given(stringMessageConverter.canWrite(String.class, null)).willReturn(true); given(stringMessageConverter.getSupportedMediaTypes()).willReturn(supported); given(stringMessageConverter.canWrite(String.class, accepted)).willReturn(true); processor.handleReturnValue(body, returnTypeStringProduces, mavContainer, webRequest); assertTrue(mavContainer.isRequestHandled()); verify(stringMessageConverter).write(eq(body), eq(accepted), isA(HttpOutputMessage.class)); }