Backported JSON converter alignment (supports method, exception messages)

Includes deprecation of getTypeToken method in GsonHttpMessageConverter.

Issue: SPR-15381
This commit is contained in:
Juergen Hoeller 2017-04-13 15:58:53 +02:00
parent 421fabb2c4
commit 3c8fc46568
4 changed files with 53 additions and 68 deletions

View File

@ -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.
@ -29,6 +29,7 @@ import org.springframework.http.StreamingHttpOutputMessage;
* Abstract base class for most {@link GenericHttpMessageConverter} implementations.
*
* @author Sebastien Deleuze
* @author Juergen Hoeller
* @since 4.2
*/
public abstract class AbstractGenericHttpMessageConverter<T> extends AbstractHttpMessageConverter<T>
@ -58,9 +59,14 @@ public abstract class AbstractGenericHttpMessageConverter<T> extends AbstractHtt
}
@Override
protected boolean supports(Class<?> clazz) {
return true;
}
@Override
public boolean canRead(Type type, Class<?> contextClass, MediaType mediaType) {
return canRead(contextClass, mediaType);
return (type instanceof Class ? canRead((Class<?>) type, mediaType) : canRead(mediaType));
}
@Override
@ -102,7 +108,6 @@ public abstract class AbstractGenericHttpMessageConverter<T> extends AbstractHtt
}
}
@Override
protected void writeInternal(T t, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
@ -113,7 +118,7 @@ public abstract class AbstractGenericHttpMessageConverter<T> extends AbstractHtt
/**
* Abstract template method that writes the actual body. Invoked from {@link #write}.
* @param t the object to write to the output message
* @param type the type of object to write, can be {@code null} if not specified.
* @param type the type of object to write (may be {@code null})
* @param outputMessage the HTTP output message to write to
* @throws IOException in case of I/O errors
* @throws HttpMessageNotWritableException in case of conversion errors

View File

@ -50,31 +50,6 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
}
@Override
protected boolean supports(Class<?> clazz) {
// should not be called as we override canRead/canWrite
return false;
}
@Override
public boolean canRead(Type type, Class<?> contextClass, MediaType mediaType) {
return false;
}
@Override
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
protected ResourceRegion readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
return null;
}
@Override
@SuppressWarnings("unchecked")
protected MediaType getDefaultContentType(Object object) {
@ -92,6 +67,30 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
return MediaType.APPLICATION_OCTET_STREAM;
}
@Override
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return false;
}
@Override
public boolean canRead(Type type, Class<?> contextClass, MediaType mediaType) {
return false;
}
@Override
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
throw new UnsupportedOperationException();
}
@Override
protected ResourceRegion readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
throw new UnsupportedOperationException();
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return canWrite(clazz, null, mediaType);
@ -100,7 +99,7 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
@Override
public boolean canWrite(Type type, Class<?> clazz, MediaType mediaType) {
if (!(type instanceof ParameterizedType)) {
return ResourceRegion.class.isAssignableFrom((Class) type);
return ResourceRegion.class.isAssignableFrom((Class<?>) type);
}
ParameterizedType parameterizedType = (ParameterizedType) type;
if (!(parameterizedType.getRawType() instanceof Class)) {
@ -140,6 +139,7 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
}
}
protected void writeResourceRegion(ResourceRegion region, HttpOutputMessage outputMessage) throws IOException {
Assert.notNull(region, "ResourceRegion must not be null");
HttpHeaders responseHeaders = outputMessage.getHeaders();
@ -197,8 +197,6 @@ public class ResourceRegionHttpMessageConverter extends AbstractGenericHttpMessa
print(out, "--" + boundaryString + "--");
}
private static void println(OutputStream os) throws IOException {
os.write('\r');
os.write('\n');

View File

@ -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.
@ -203,12 +203,6 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener
}
}
@Override
protected boolean supports(Class<?> clazz) {
// should not be called, since we override canRead/Write instead
throw new UnsupportedOperationException();
}
@Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
@ -237,7 +231,7 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener
return this.objectMapper.readValue(inputMessage.getBody(), javaType);
}
catch (IOException ex) {
throw new HttpMessageNotReadableException("Could not read document: " + ex.getMessage(), ex);
throw new HttpMessageNotReadableException("Could not read JSON document: " + ex.getMessage(), ex);
}
}
@ -289,7 +283,7 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener
}
catch (JsonProcessingException ex) {
throw new HttpMessageNotWritableException("Could not write content: " + ex.getMessage(), ex);
throw new HttpMessageNotWritableException("Could not write JSON document: " + ex.getMessage(), ex);
}
}

View File

@ -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.
@ -114,30 +114,7 @@ public class GsonHttpMessageConverter extends AbstractGenericHttpMessageConverte
@Override
public boolean canRead(Class<?> clazz, MediaType mediaType) {
return canRead(mediaType);
}
@Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return canWrite(mediaType);
}
@Override
protected boolean supports(Class<?> clazz) {
// should not be called, since we override canRead/Write instead
throw new UnsupportedOperationException();
}
@Override
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
TypeToken<?> token = getTypeToken(clazz);
return readTypeToken(token, inputMessage);
}
@Override
@SuppressWarnings("deprecation")
public Object read(Type type, Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
@ -145,6 +122,15 @@ public class GsonHttpMessageConverter extends AbstractGenericHttpMessageConverte
return readTypeToken(token, inputMessage);
}
@Override
@SuppressWarnings("deprecation")
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
TypeToken<?> token = getTypeToken(clazz);
return readTypeToken(token, inputMessage);
}
/**
* Return the Gson {@link TypeToken} for the specified type.
* <p>The default implementation returns {@code TypeToken.get(type)}, but
@ -162,7 +148,9 @@ public class GsonHttpMessageConverter extends AbstractGenericHttpMessageConverte
* </pre>
* @param type the type for which to return the TypeToken
* @return the type token
* @deprecated as of Spring Framework 4.3.8, in favor of signature-based resolution
*/
@Deprecated
protected TypeToken<?> getTypeToken(Type type) {
return TypeToken.get(type);
}
@ -173,7 +161,7 @@ public class GsonHttpMessageConverter extends AbstractGenericHttpMessageConverte
return this.gson.fromJson(json, token.getType());
}
catch (JsonParseException ex) {
throw new HttpMessageNotReadableException("Could not read JSON: " + ex.getMessage(), ex);
throw new HttpMessageNotReadableException("Could not read JSON document: " + ex.getMessage(), ex);
}
}
@ -203,7 +191,7 @@ public class GsonHttpMessageConverter extends AbstractGenericHttpMessageConverte
writer.close();
}
catch (JsonIOException ex) {
throw new HttpMessageNotWritableException("Could not write JSON: " + ex.getMessage(), ex);
throw new HttpMessageNotWritableException("Could not write JSON document: " + ex.getMessage(), ex);
}
}