relaxed generic Class declaration in HttpMessageConverter's canRead/canWrite/read signatures (SPR-6848)

This commit is contained in:
Juergen Hoeller 2010-02-16 17:46:16 +00:00
parent 19cdd558d3
commit 4ae1709313
13 changed files with 197 additions and 188 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,11 +34,12 @@ import org.springframework.util.Assert;
/** /**
* Abstract base class for most {@link HttpMessageConverter} implementations. * Abstract base class for most {@link HttpMessageConverter} implementations.
* *
* <p>This base class adds support for setting supported {@code MediaTypes}, through the {@link * <p>This base class adds support for setting supported {@code MediaTypes}, through the
* #setSupportedMediaTypes(List) supportedMediaTypes} bean property. It also adds support for {@code Content-Type} and * {@link #setSupportedMediaTypes(List) supportedMediaTypes} bean property. It also adds
* {@code Content-Length} when writing to output messages. * support for {@code Content-Type} and {@code Content-Length} when writing to output messages.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
*/ */
public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> { public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {
@ -48,9 +49,9 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
private List<MediaType> supportedMediaTypes = Collections.emptyList(); private List<MediaType> supportedMediaTypes = Collections.emptyList();
/** /**
* Construct an {@code AbstractHttpMessageConverter} with no supported media types. * Construct an {@code AbstractHttpMessageConverter} with no supported media types.
*
* @see #setSupportedMediaTypes * @see #setSupportedMediaTypes
*/ */
protected AbstractHttpMessageConverter() { protected AbstractHttpMessageConverter() {
@ -58,7 +59,6 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
/** /**
* Construct an {@code AbstractHttpMessageConverter} with one supported media type. * Construct an {@code AbstractHttpMessageConverter} with one supported media type.
*
* @param supportedMediaType the supported media type * @param supportedMediaType the supported media type
*/ */
protected AbstractHttpMessageConverter(MediaType supportedMediaType) { protected AbstractHttpMessageConverter(MediaType supportedMediaType) {
@ -67,14 +67,16 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
/** /**
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type. * Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
*
* @param supportedMediaTypes the supported media types * @param supportedMediaTypes the supported media types
*/ */
protected AbstractHttpMessageConverter(MediaType... supportedMediaTypes) { protected AbstractHttpMessageConverter(MediaType... supportedMediaTypes) {
setSupportedMediaTypes(Arrays.asList(supportedMediaTypes)); setSupportedMediaTypes(Arrays.asList(supportedMediaTypes));
} }
/** Set the list of {@link MediaType} objects supported by this converter. */
/**
* Set the list of {@link MediaType} objects supported by this converter.
*/
public void setSupportedMediaTypes(List<MediaType> supportedMediaTypes) { public void setSupportedMediaTypes(List<MediaType> supportedMediaTypes) {
Assert.notEmpty(supportedMediaTypes, "'supportedMediaTypes' must not be empty"); Assert.notEmpty(supportedMediaTypes, "'supportedMediaTypes' must not be empty");
this.supportedMediaTypes = new ArrayList<MediaType>(supportedMediaTypes); this.supportedMediaTypes = new ArrayList<MediaType>(supportedMediaTypes);
@ -84,21 +86,20 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
return Collections.unmodifiableList(this.supportedMediaTypes); return Collections.unmodifiableList(this.supportedMediaTypes);
} }
/** /**
* {@inheritDoc} * {@inheritDoc}
* * <p>This implementation checks if the given class is {@linkplain #supports(Class) supported},
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported}, and if the {@linkplain * and if the {@linkplain #getSupportedMediaTypes() supported media types}
* #getSupportedMediaTypes() supported media types} {@linkplain MediaType#includes(MediaType) include} the given media * {@linkplain MediaType#includes(MediaType) include} the given media type.
* type.
*/ */
public boolean canRead(Class<?> clazz, MediaType mediaType) { public boolean canRead(Class<?> clazz, MediaType mediaType) {
return supports(clazz) && canRead(mediaType); return supports(clazz) && canRead(mediaType);
} }
/** /**
* Returns true if any of the {@linkplain #setSupportedMediaTypes(List) supported media types} include the given media * Returns true if any of the {@linkplain #setSupportedMediaTypes(List) supported media types}
* type. * include the given media type.
*
* @param mediaType the media type * @param mediaType the media type
* @return true if the supported media types include the media type, or if the media type is {@code null} * @return true if the supported media types include the media type, or if the media type is {@code null}
*/ */
@ -116,10 +117,9 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
/** /**
* {@inheritDoc} * {@inheritDoc}
* * <p>This implementation checks if the given class is {@linkplain #supports(Class) supported},
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported}, and if the {@linkplain * and if the {@linkplain #getSupportedMediaTypes() supported media types}
* #getSupportedMediaTypes() supported media types} {@linkplain MediaType#includes(MediaType) include} the given media * {@linkplain MediaType#includes(MediaType) include} the given media type.
* type.
*/ */
public boolean canWrite(Class<?> clazz, MediaType mediaType) { public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return supports(clazz) && canWrite(mediaType); return supports(clazz) && canWrite(mediaType);
@ -128,7 +128,6 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
/** /**
* Returns true if the given media type includes any of the * Returns true if the given media type includes any of the
* {@linkplain #setSupportedMediaTypes(List) supported media types}. * {@linkplain #setSupportedMediaTypes(List) supported media types}.
*
* @param mediaType the media type * @param mediaType the media type
* @return true if the supported media types include the media type, or if the media type is {@code null} * @return true if the supported media types include the media type, or if the media type is {@code null}
*/ */
@ -144,45 +143,24 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
return false; return false;
} }
/**
* Indicates whether the given class is supported by this converter.
*
* @param clazz the class to test for support
* @return <code>true</code> if supported; <code>false</code> otherwise
*/
protected abstract boolean supports(Class<?> clazz);
/** /**
* {@inheritDoc} * {@inheritDoc}
* * <p>This implementation simple delegates to {@link #readInternal(Class, HttpInputMessage)}.
* <p>This implementation simple delegates to {@link #readInternal(Class, HttpInputMessage)}. Future implementations * Future implementations might add some default behavior, however.
* might add some default behavior, however.
*/ */
public final T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException { public final T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException {
return readInternal(clazz, inputMessage); return readInternal(clazz, inputMessage);
} }
/**
* Abstract template method that reads the actualy object. Invoked from {@link #read(Class, HttpInputMessage)}.
*
* @param clazz the type of object to return
* @param inputMessage the HTTP input message to read from
* @return the converted object
* @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors
*/
protected abstract T readInternal(Class<T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/** /**
* {@inheritDoc} * {@inheritDoc}
* * <p>This implementation delegates to {@link #getDefaultContentType(Object)} if a content
* <p>This implementation delegates to {@link #getDefaultContentType(Object)} if a content type was not provided, calls * type was not provided, calls {@link #getContentLength}, and sets the corresponding headers
* {@link #getContentLength}, and sets the corresponding headers on the output message. It then calls {@link * on the output message. It then calls {@link #writeInternal}.
* #writeInternal}.
*/ */
public final void write(T t, MediaType contentType, HttpOutputMessage outputMessage) public final void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException { throws IOException, HttpMessageNotWritableException {
HttpHeaders headers = outputMessage.getHeaders(); HttpHeaders headers = outputMessage.getHeaders();
if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) { if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) {
contentType = getDefaultContentType(t); contentType = getDefaultContentType(t);
@ -199,12 +177,11 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
} }
/** /**
* Returns the default content type for the given type. Called when {@link #write} is invoked without a specified * Returns the default content type for the given type. Called when {@link #write}
* content type parameter. * is invoked without a specified content type parameter.
* * <p>By default, this returns the first element of the
* <p>By default, this returns the first element of the {@link #setSupportedMediaTypes(List) supportedMediaTypes} * {@link #setSupportedMediaTypes(List) supportedMediaTypes} property, if any.
* property, if any. Can be overriden in subclasses. * Can be overridden in subclasses.
*
* @param t the type to return the content type for * @param t the type to return the content type for
* @return the content type, or <code>null</code> if not known * @return the content type, or <code>null</code> if not known
*/ */
@ -215,10 +192,8 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
/** /**
* Returns the content length for the given type. * Returns the content length for the given type.
* * <p>By default, this returns {@code null}, meaning that the content length is unknown.
* <p>By default, this returns {@code null}, meaning that the content length is unknown. Can be overriden in * Can be overridden in subclasses.
* subclasses.
*
* @param t the type to return the content length for * @param t the type to return the content length for
* @return the content length, or {@code null} if not known * @return the content length, or {@code null} if not known
*/ */
@ -226,9 +201,27 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
return null; return null;
} }
/**
* Indicates whether the given class is supported by this converter.
* @param clazz the class to test for support
* @return <code>true</code> if supported; <code>false</code> otherwise
*/
protected abstract boolean supports(Class<?> clazz);
/**
* Abstract template method that reads the actualy object. Invoked from {@link #read}.
* @param clazz the type of object to return
* @param inputMessage the HTTP input message to read from
* @return the converted object
* @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors
*/
protected abstract T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/** /**
* Abstract template method that writes the actual body. Invoked from {@link #write}. * Abstract template method that writes the actual body. Invoked from {@link #write}.
*
* @param t the object to write to the output message * @param t the object to write to the output message
* @param outputMessage the message to write to * @param outputMessage the message to write to
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -62,37 +62,27 @@ import org.springframework.util.Assert;
*/ */
public class BufferedImageHttpMessageConverter implements HttpMessageConverter<BufferedImage> { public class BufferedImageHttpMessageConverter implements HttpMessageConverter<BufferedImage> {
private List<MediaType> readableMediaTypes = new ArrayList<MediaType>(); private final List<MediaType> readableMediaTypes = new ArrayList<MediaType>();
private MediaType defaultContentType; private MediaType defaultContentType;
private File cacheDir; private File cacheDir;
public BufferedImageHttpMessageConverter() { public BufferedImageHttpMessageConverter() {
String[] readerMediaTypes = ImageIO.getReaderMIMETypes(); String[] readerMediaTypes = ImageIO.getReaderMIMETypes();
for (String mediaType : readerMediaTypes) { for (String mediaType : readerMediaTypes) {
readableMediaTypes.add(MediaType.parseMediaType(mediaType)); this.readableMediaTypes.add(MediaType.parseMediaType(mediaType));
} }
String[] writerMediaTypes = ImageIO.getWriterMIMETypes(); String[] writerMediaTypes = ImageIO.getWriterMIMETypes();
if (writerMediaTypes.length > 0) { if (writerMediaTypes.length > 0) {
defaultContentType = MediaType.parseMediaType(writerMediaTypes[0]); this.defaultContentType = MediaType.parseMediaType(writerMediaTypes[0]);
} }
} }
/**
* Returns the default {@code Content-Type} to be used for writing. Called when {@link #write} is invoked without a
* specified content type parameter.
*
* @return the default content type
*/
public MediaType getDefaultContentType() {
return defaultContentType;
}
/** /**
* Sets the default {@code Content-Type} to be used for writing. * Sets the default {@code Content-Type} to be used for writing.
*
* @throws IllegalArgumentException if the given content type is not supported by the Java Image I/O API * @throws IllegalArgumentException if the given content type is not supported by the Java Image I/O API
*/ */
public void setDefaultContentType(MediaType defaultContentType) { public void setDefaultContentType(MediaType defaultContentType) {
@ -106,20 +96,27 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
this.defaultContentType = defaultContentType; this.defaultContentType = defaultContentType;
} }
/** Sets the cache directory. If this property is set to an existing directory, this converter will cache image data. */ /**
* Returns the default {@code Content-Type} to be used for writing.
* Called when {@link #write} is invoked without a specified content type parameter.
*/
public MediaType getDefaultContentType() {
return this.defaultContentType;
}
/**
* Sets the cache directory. If this property is set to an existing directory,
* this converter will cache image data.
*/
public void setCacheDir(File cacheDir) { public void setCacheDir(File cacheDir) {
Assert.notNull(cacheDir, "'cacheDir' must not be null"); Assert.notNull(cacheDir, "'cacheDir' must not be null");
Assert.isTrue(cacheDir.isDirectory(), "'cacheDir' is not a directory"); Assert.isTrue(cacheDir.isDirectory(), "'cacheDir' is not a directory");
this.cacheDir = cacheDir; this.cacheDir = cacheDir;
} }
public boolean canRead(Class<?> clazz, MediaType mediaType) { public boolean canRead(Class<?> clazz, MediaType mediaType) {
if (BufferedImage.class.equals(clazz)) { return (BufferedImage.class.equals(clazz) && isReadable(mediaType));
return isReadable(mediaType);
}
else {
return false;
}
} }
private boolean isReadable(MediaType mediaType) { private boolean isReadable(MediaType mediaType) {
@ -131,12 +128,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
} }
public boolean canWrite(Class<?> clazz, MediaType mediaType) { public boolean canWrite(Class<?> clazz, MediaType mediaType) {
if (BufferedImage.class.equals(clazz)) { return (BufferedImage.class.equals(clazz) && isWritable(mediaType));
return isWritable(mediaType);
}
else {
return false;
}
} }
private boolean isWritable(MediaType mediaType) { private boolean isWritable(MediaType mediaType) {
@ -148,11 +140,12 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
} }
public List<MediaType> getSupportedMediaTypes() { public List<MediaType> getSupportedMediaTypes() {
return Collections.unmodifiableList(readableMediaTypes); return Collections.unmodifiableList(this.readableMediaTypes);
} }
public BufferedImage read(Class<BufferedImage> clazz, HttpInputMessage inputMessage) public BufferedImage read(Class<? extends BufferedImage> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException { throws IOException, HttpMessageNotReadableException {
ImageInputStream imageInputStream = null; ImageInputStream imageInputStream = null;
ImageReader imageReader = null; ImageReader imageReader = null;
try { try {
@ -187,7 +180,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
} }
private ImageInputStream createImageInputStream(InputStream is) throws IOException { private ImageInputStream createImageInputStream(InputStream is) throws IOException {
if (cacheDir != null) { if (this.cacheDir != null) {
return new FileCacheImageInputStream(is, cacheDir); return new FileCacheImageInputStream(is, cacheDir);
} }
else { else {
@ -197,6 +190,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
public void write(BufferedImage image, MediaType contentType, HttpOutputMessage outputMessage) public void write(BufferedImage image, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException { throws IOException, HttpMessageNotWritableException {
if (contentType == null) { if (contentType == null) {
contentType = getDefaultContentType(); contentType = getDefaultContentType();
} }
@ -236,17 +230,17 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
} }
private ImageOutputStream createImageOutputStream(OutputStream os) throws IOException { private ImageOutputStream createImageOutputStream(OutputStream os) throws IOException {
if (cacheDir != null) { if (this.cacheDir != null) {
return new FileCacheImageOutputStream(os, cacheDir); return new FileCacheImageOutputStream(os, this.cacheDir);
} }
else { else {
return new MemoryCacheImageOutputStream(os); return new MemoryCacheImageOutputStream(os);
} }
} }
/** /**
* Template method that allows for manipulating the {@link ImageReadParam} before it is used to read an image. * Template method that allows for manipulating the {@link ImageReadParam} before it is used to read an image.
*
* <p>Default implementation is empty. * <p>Default implementation is empty.
*/ */
protected void process(ImageReadParam irp) { protected void process(ImageReadParam irp) {
@ -254,9 +248,9 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
/** /**
* Template method that allows for manipulating the {@link ImageWriteParam} before it is used to write an image. * Template method that allows for manipulating the {@link ImageWriteParam} before it is used to write an image.
*
* <p>Default implementation is empty. * <p>Default implementation is empty.
*/ */
protected void process(ImageWriteParam iwp) { protected void process(ImageWriteParam iwp) {
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -47,7 +47,7 @@ public class ByteArrayHttpMessageConverter extends AbstractHttpMessageConverter<
} }
@Override @Override
public byte[] readInternal(Class<byte[]> clazz, HttpInputMessage inputMessage) throws IOException { public byte[] readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
long contentLength = inputMessage.getHeaders().getContentLength(); long contentLength = inputMessage.getHeaders().getContentLength();
if (contentLength >= 0) { if (contentLength >= 0) {
ByteArrayOutputStream bos = new ByteArrayOutputStream((int) contentLength); ByteArrayOutputStream bos = new ByteArrayOutputStream((int) contentLength);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -50,19 +50,20 @@ public class FormHttpMessageConverter extends AbstractHttpMessageConverter<Multi
public static final Charset DEFAULT_CHARSET = Charset.forName(WebUtils.DEFAULT_CHARACTER_ENCODING); public static final Charset DEFAULT_CHARSET = Charset.forName(WebUtils.DEFAULT_CHARACTER_ENCODING);
/** Creates a new instance of the {@code FormHttpMessageConverter}. */ /** Creates a new instance of the {@code FormHttpMessageConverter}. */
public FormHttpMessageConverter() { public FormHttpMessageConverter() {
super(new MediaType("application", "x-www-form-urlencoded")); super(new MediaType("application", "x-www-form-urlencoded"));
} }
@Override @Override
public boolean supports(Class<?> clazz) { public boolean supports(Class<?> clazz) {
return MultiValueMap.class.isAssignableFrom(clazz); return MultiValueMap.class.isAssignableFrom(clazz);
} }
@Override @Override
public MultiValueMap<String, String> readInternal(Class<MultiValueMap<String, String>> clazz, public MultiValueMap<String, String> readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
HttpInputMessage inputMessage) throws IOException {
MediaType contentType = inputMessage.getHeaders().getContentType(); MediaType contentType = inputMessage.getHeaders().getContentType();
Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET; Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET;
String body = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset)); String body = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
@ -112,4 +113,5 @@ public class FormHttpMessageConverter extends AbstractHttpMessageConverter<Multi
} }
FileCopyUtils.copy(builder.toString(), new OutputStreamWriter(outputMessage.getBody(), charset)); FileCopyUtils.copy(builder.toString(), new OutputStreamWriter(outputMessage.getBody(), charset));
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -27,6 +27,7 @@ import org.springframework.http.MediaType;
* Strategy interface that specifies a converter that can convert from and to HTTP requests and responses. * Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Juergen Hoeller
* @since 3.0 * @since 3.0
*/ */
public interface HttpMessageConverter<T> { public interface HttpMessageConverter<T> {
@ -55,23 +56,24 @@ public interface HttpMessageConverter<T> {
/** /**
* Read an object of the given type form the given input message, and returns it. * Read an object of the given type form the given input message, and returns it.
* @param clazz the type of object to return. This type must have previously been passed to the {@link #canRead * @param clazz the type of object to return. This type must have previously been passed to the
* canRead} method of this interface, which must have returned {@code true}. * {@link #canRead canRead} method of this interface, which must have returned {@code true}.
* @param inputMessage the HTTP input message to read from * @param inputMessage the HTTP input message to read from
* @return the converted object * @return the converted object
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors
* @throws HttpMessageNotReadableException in case of conversion errors * @throws HttpMessageNotReadableException in case of conversion errors
*/ */
T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException;
/** /**
* Write an given object to the given output message. * Write an given object to the given output message.
* * @param t the object to write to the output message. The type of this object must have previously been
* @param t the object to write to the output message. The type of this object must have previously been passed to the * passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
* {@link #canWrite canWrite} method of this interface, which must have returned {@code true}. * @param contentType the content type to use when writing. May be {@code null} to indicate that the
* @param contentType the content type to use when writing. May be {@code null} to indicate that the the default * default content type of the converter must be used. If not {@code null}, this media type must have
* content type of the converter must be used. If not {@code null}, this media type must have previously been passed to * previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
* the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}. * returned {@code true}.
* @param outputMessage the message to write to * @param outputMessage the message to write to
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors
* @throws HttpMessageNotWritableException in case of conversion errors * @throws HttpMessageNotWritableException in case of conversion errors

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -56,7 +56,7 @@ public class StringHttpMessageConverter extends AbstractHttpMessageConverter<Str
} }
@Override @Override
public String readInternal(Class<String> clazz, HttpInputMessage inputMessage) throws IOException { protected String readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
MediaType contentType = inputMessage.getHeaders().getContentType(); MediaType contentType = inputMessage.getHeaders().getContentType();
Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET; Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET;
return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset)); return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,18 +35,17 @@ import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.util.Assert; import org.springframework.util.Assert;
/** /**
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverter} that can read * Implementation of {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverter}
* and write JSON using <a href="http://jackson.codehaus.org/">Jackson's</a> {@link ObjectMapper}. * that can read and write JSON using <a href="http://jackson.codehaus.org/">Jackson's</a> {@link ObjectMapper}.
* *
* <p>This converter can be used to bind to typed beans, or untyped {@link java.util.HashMap HashMap} instances. * <p>This converter can be used to bind to typed beans, or untyped {@link java.util.HashMap HashMap} instances.
* *
* <p>By default, this converter supports {@code application/json}. This can be overridden by setting the {@link * <p>By default, this converter supports {@code application/json}. This can be overridden by setting the
* #setSupportedMediaTypes(List) supportedMediaTypes} property. * {@link #setSupportedMediaTypes(List) supportedMediaTypes} property.
* method.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @see org.springframework.web.servlet.view.json.BindingJacksonJsonView
* @since 3.0 * @since 3.0
* @see org.springframework.web.servlet.view.json.BindingJacksonJsonView
*/ */
public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConverter<Object> { public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
@ -56,15 +55,17 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
private boolean prefixJson = false; private boolean prefixJson = false;
/** Construct a new {@code BindingJacksonHttpMessageConverter}, */
/**
* Construct a new {@code BindingJacksonHttpMessageConverter}.
*/
public MappingJacksonHttpMessageConverter() { public MappingJacksonHttpMessageConverter() {
super(new MediaType("application", "json", DEFAULT_CHARSET)); super(new MediaType("application", "json", DEFAULT_CHARSET));
} }
/** /**
* Sets the {@code ObjectMapper} for this view. If not set, a default {@link ObjectMapper#ObjectMapper() ObjectMapper} * Sets the {@code ObjectMapper} for this view. If not set, a default
* is used. * {@link ObjectMapper#ObjectMapper() ObjectMapper} is used.
*
* <p>Setting a custom-configured {@code ObjectMapper} is one way to take further control of the JSON serialization * <p>Setting a custom-configured {@code ObjectMapper} is one way to take further control of the JSON serialization
* process. For example, an extended {@link org.codehaus.jackson.map.SerializerFactory} can be configured that provides * process. For example, an extended {@link org.codehaus.jackson.map.SerializerFactory} can be configured that provides
* custom serializers for specific types. The other option for refining the serialization process is to use Jackson's * custom serializers for specific types. The other option for refining the serialization process is to use Jackson's
@ -77,7 +78,6 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
/** /**
* Indicates whether the JSON output by this view should be prefixed with "{} &&". Default is false. * Indicates whether the JSON output by this view should be prefixed with "{} &&". Default is false.
*
* <p> Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. The prefix renders the string * <p> Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. The prefix renders the string
* syntactically invalid as a script so that it cannot be hijacked. This prefix does not affect the evaluation of JSON, * syntactically invalid as a script so that it cannot be hijacked. This prefix does not affect the evaluation of JSON,
* but if JSON validation is performed on the string, the prefix would need to be ignored. * but if JSON validation is performed on the string, the prefix would need to be ignored.
@ -86,39 +86,42 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
this.prefixJson = prefixJson; this.prefixJson = prefixJson;
} }
@Override @Override
public boolean canRead(Class<?> clazz, MediaType mediaType) { public boolean canRead(Class<?> clazz, MediaType mediaType) {
JavaType javaType = TypeFactory.fromClass(clazz); JavaType javaType = TypeFactory.fromClass(clazz);
return objectMapper.canDeserialize(javaType) && canRead(mediaType); return this.objectMapper.canDeserialize(javaType) && canRead(mediaType);
} }
@Override @Override
public boolean canWrite(Class<?> clazz, MediaType mediaType) { public boolean canWrite(Class<?> clazz, MediaType mediaType) {
return objectMapper.canSerialize(clazz) && canWrite(mediaType); return this.objectMapper.canSerialize(clazz) && canWrite(mediaType);
} }
@Override @Override
protected boolean supports(Class<?> clazz) { protected boolean supports(Class<?> clazz) {
// should not be called, since we override canRead/Write // should not be called, since we override canRead/Write instead
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override @Override
protected Object readInternal(Class<Object> clazz, HttpInputMessage inputMessage) protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException { throws IOException, HttpMessageNotReadableException {
return objectMapper.readValue(inputMessage.getBody(), clazz);
return this.objectMapper.readValue(inputMessage.getBody(), clazz);
} }
@Override @Override
protected void writeInternal(Object o, HttpOutputMessage outputMessage) protected void writeInternal(Object o, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException { throws IOException, HttpMessageNotWritableException {
JsonEncoding encoding = getEncoding(outputMessage.getHeaders().getContentType()); JsonEncoding encoding = getEncoding(outputMessage.getHeaders().getContentType());
JsonGenerator jsonGenerator = JsonGenerator jsonGenerator =
objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding); this.objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
if (prefixJson) { if (this.prefixJson) {
jsonGenerator.writeRaw("{} && "); jsonGenerator.writeRaw("{} && ");
} }
objectMapper.writeValue(jsonGenerator, o); this.objectMapper.writeValue(jsonGenerator, o);
} }
private JsonEncoding getEncoding(MediaType contentType) { private JsonEncoding getEncoding(MediaType contentType) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,7 +19,6 @@ package org.springframework.http.converter.xml;
import java.io.IOException; import java.io.IOException;
import javax.xml.transform.Result; import javax.xml.transform.Result;
import javax.xml.transform.Source; import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
@ -33,8 +32,8 @@ import org.springframework.http.converter.AbstractHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConversionException; import org.springframework.http.converter.HttpMessageConversionException;
/** /**
* Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters} that * Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters}
* convert from/to XML. * that convert from/to XML.
* *
* <p>By default, subclasses of this converter support {@code text/xml}, {@code application/xml}, and {@code * <p>By default, subclasses of this converter support {@code text/xml}, {@code application/xml}, and {@code
* application/*-xml}. This can be overridden by setting the {@link #setSupportedMediaTypes(java.util.List) * application/*-xml}. This can be overridden by setting the {@link #setSupportedMediaTypes(java.util.List)
@ -47,58 +46,58 @@ public abstract class AbstractXmlHttpMessageConverter<T> extends AbstractHttpMes
private final TransformerFactory transformerFactory = TransformerFactory.newInstance(); private final TransformerFactory transformerFactory = TransformerFactory.newInstance();
/** /**
* Protected constructor that sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes} to {@code * Protected constructor that sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes}
* text/xml} and {@code application/xml}, and {@code application/*-xml}. * to {@code text/xml} and {@code application/xml}, and {@code application/*-xml}.
*/ */
protected AbstractXmlHttpMessageConverter() { protected AbstractXmlHttpMessageConverter() {
super(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml")); super(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"));
} }
/** Invokes {@link #readFromSource(Class, HttpHeaders, Source)}. */
@Override @Override
public final T readInternal(Class<T> clazz, HttpInputMessage inputMessage) throws IOException { public final T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException {
return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputMessage.getBody())); return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputMessage.getBody()));
} }
/**
* Abstract template method called from {@link #read(Class, HttpInputMessage)}.
*
* @param clazz the type of object to return
* @param headers the HTTP input headers
* @param source the HTTP input body
* @return the converted object
* @throws IOException in case of I/O errors
* @throws org.springframework.http.converter.HttpMessageConversionException in case of conversion errors
*/
protected abstract T readFromSource(Class<T> clazz, HttpHeaders headers, Source source) throws IOException;
@Override @Override
protected final void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException { protected final void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException {
writeToResult(t, outputMessage.getHeaders(), new StreamResult(outputMessage.getBody())); writeToResult(t, outputMessage.getHeaders(), new StreamResult(outputMessage.getBody()));
} }
/**
* Transforms the given {@code Source} to the {@code Result}.
* @param source the source to transform from
* @param result the result to transform to
* @throws HttpMessageConversionException in case of transformation errors
*/
protected void transform(Source source, Result result) throws TransformerException {
this.transformerFactory.newTransformer().transform(source, result);
}
/**
* Abstract template method called from {@link #read(Class, HttpInputMessage)}.
* @param clazz the type of object to return
* @param headers the HTTP input headers
* @param source the HTTP input body
* @return the converted object
* @throws IOException in case of I/O errors
* @throws org.springframework.http.converter.HttpMessageConversionException in case of conversion errors
*/
protected abstract T readFromSource(Class<? extends T> clazz, HttpHeaders headers, Source source)
throws IOException;
/** /**
* Abstract template method called from {@link #writeInternal(Object, HttpOutputMessage)}. * Abstract template method called from {@link #writeInternal(Object, HttpOutputMessage)}.
*
* @param t the object to write to the output message * @param t the object to write to the output message
* @param headers the HTTP output headers * @param headers the HTTP output headers
* @param result the HTTP output body * @param result the HTTP output body
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors
* @throws HttpMessageConversionException in case of conversion errors * @throws HttpMessageConversionException in case of conversion errors
*/ */
protected abstract void writeToResult(T t, HttpHeaders headers, Result result) throws IOException; protected abstract void writeToResult(T t, HttpHeaders headers, Result result)
throws IOException;
/**
* Transforms the given {@code Source} to the {@code Result}.
*
* @param source the source to transform from
* @param result the result to transform to
* @throws HttpMessageConversionException in case of transformation errors
*/
protected void transform(Source source, Result result) throws TransformerException {
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(source, result);
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -67,14 +67,14 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
} }
@Override @Override
protected Object readFromSource(Class<Object> clazz, HttpHeaders headers, Source source) throws IOException { protected Object readFromSource(Class<?> clazz, HttpHeaders headers, Source source) throws IOException {
try { try {
Unmarshaller unmarshaller = createUnmarshaller(clazz); Unmarshaller unmarshaller = createUnmarshaller(clazz);
if (clazz.isAnnotationPresent(XmlRootElement.class)) { if (clazz.isAnnotationPresent(XmlRootElement.class)) {
return unmarshaller.unmarshal(source); return unmarshaller.unmarshal(source);
} }
else { else {
JAXBElement<Object> jaxbElement = unmarshaller.unmarshal(source, clazz); JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);
return jaxbElement.getValue(); return jaxbElement.getValue();
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -49,6 +49,7 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
private Unmarshaller unmarshaller; private Unmarshaller unmarshaller;
/** /**
* Construct a new {@code MarshallingHttpMessageConverter} with no {@link Marshaller} or {@link Unmarshaller} set. The * Construct a new {@code MarshallingHttpMessageConverter} with no {@link Marshaller} or {@link Unmarshaller} set. The
* marshaller and unmarshaller must be set after construction by invoking {@link #setMarshaller(Marshaller)} and {@link * marshaller and unmarshaller must be set after construction by invoking {@link #setMarshaller(Marshaller)} and {@link
@ -62,7 +63,6 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
* Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and unmarshalling. * Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and unmarshalling.
* Otherwise, an exception is thrown. <p>Note that all {@code Marshaller} implementations in Spring also implement the * Otherwise, an exception is thrown. <p>Note that all {@code Marshaller} implementations in Spring also implement the
* {@code Unmarshaller} interface, so that you can safely use this constructor. * {@code Unmarshaller} interface, so that you can safely use this constructor.
*
* @param marshaller object used as marshaller and unmarshaller * @param marshaller object used as marshaller and unmarshaller
*/ */
public MarshallingHttpMessageConverter(Marshaller marshaller) { public MarshallingHttpMessageConverter(Marshaller marshaller) {
@ -76,7 +76,6 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
/** /**
* Construct a new <code>MarshallingMessageConverter</code> with the given {@code Marshaller} and {@code * Construct a new <code>MarshallingMessageConverter</code> with the given {@code Marshaller} and {@code
* Unmarshaller}. * Unmarshaller}.
*
* @param marshaller the Marshaller to use * @param marshaller the Marshaller to use
* @param unmarshaller the Unmarshaller to use * @param unmarshaller the Unmarshaller to use
*/ */
@ -87,26 +86,31 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
this.unmarshaller = unmarshaller; this.unmarshaller = unmarshaller;
} }
/** Set the {@link Marshaller} to be used by this message converter. */ /**
* Set the {@link Marshaller} to be used by this message converter.
*/
public void setMarshaller(Marshaller marshaller) { public void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller; this.marshaller = marshaller;
} }
/** Set the {@link Unmarshaller} to be used by this message converter. */ /**
* Set the {@link Unmarshaller} to be used by this message converter.
*/
public void setUnmarshaller(Unmarshaller unmarshaller) { public void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller; this.unmarshaller = unmarshaller;
} }
@Override @Override
public boolean supports(Class<?> clazz) { public boolean supports(Class<?> clazz) {
return unmarshaller.supports(clazz); return this.unmarshaller.supports(clazz);
} }
@Override @Override
protected Object readFromSource(Class<Object> clazz, HttpHeaders headers, Source source) throws IOException { protected Object readFromSource(Class<?> clazz, HttpHeaders headers, Source source) throws IOException {
Assert.notNull(this.unmarshaller, "Property 'unmarshaller' is required"); Assert.notNull(this.unmarshaller, "Property 'unmarshaller' is required");
try { try {
return unmarshaller.unmarshal(source); return this.unmarshaller.unmarshal(source);
} }
catch (UnmarshallingFailureException ex) { catch (UnmarshallingFailureException ex) {
throw new HttpMessageNotReadableException("Could not read [" + clazz + "]", ex); throw new HttpMessageNotReadableException("Could not read [" + clazz + "]", ex);
@ -117,10 +121,11 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
protected void writeToResult(Object o, HttpHeaders headers, Result result) throws IOException { protected void writeToResult(Object o, HttpHeaders headers, Result result) throws IOException {
Assert.notNull(this.marshaller, "Property 'marshaller' is required"); Assert.notNull(this.marshaller, "Property 'marshaller' is required");
try { try {
marshaller.marshal(o, result); this.marshaller.marshal(o, result);
} }
catch (MarshallingFailureException ex) { catch (MarshallingFailureException ex) {
throw new HttpMessageNotWritableException("Could not write [" + o + "]", ex); throw new HttpMessageNotWritableException("Could not write [" + o + "]", ex);
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -36,8 +36,8 @@ import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException; import org.springframework.http.converter.HttpMessageNotWritableException;
/** /**
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter} that can read and write {@link * Implementation of {@link org.springframework.http.converter.HttpMessageConverter}
* Source} objects. * that can read and write {@link Source} objects.
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @since 3.0 * @since 3.0
@ -52,7 +52,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractXmlHtt
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
protected T readFromSource(Class<T> clazz, HttpHeaders headers, Source source) throws IOException { protected T readFromSource(Class clazz, HttpHeaders headers, Source source) throws IOException {
try { try {
if (DOMSource.class.equals(clazz)) { if (DOMSource.class.equals(clazz)) {
DOMResult domResult = new DOMResult(); DOMResult domResult = new DOMResult();
@ -93,4 +93,5 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractXmlHtt
throw new HttpMessageNotWritableException("Could not transform [" + t + "] to [" + result + "]", ex); throw new HttpMessageNotWritableException("Could not transform [" + t + "] to [" + result + "]", ex);
} }
} }
} }

View File

@ -17,10 +17,17 @@
package org.springframework.http.converter; package org.springframework.http.converter;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import javax.xml.namespace.QName;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*; import static org.junit.Assert.*;
import org.junit.Test;
import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpOutputMessage; import org.springframework.http.HttpOutputMessage;
@ -79,7 +86,7 @@ public class HttpMessageConverterTests {
} }
@Override @Override
protected T readInternal(Class<T> clazz, HttpInputMessage inputMessage) protected T readInternal(Class clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException { throws IOException, HttpMessageNotReadableException {
fail("Not expected"); fail("Not expected");
return null; return null;
@ -95,4 +102,5 @@ public class HttpMessageConverterTests {
private static class MyType { private static class MyType {
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2010 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -31,7 +31,9 @@ import org.springframework.http.MediaType;
import org.springframework.http.MockHttpInputMessage; import org.springframework.http.MockHttpInputMessage;
import org.springframework.http.MockHttpOutputMessage; import org.springframework.http.MockHttpOutputMessage;
/** @author Arjen Poutsma */ /**
* @author Arjen Poutsma
*/
public class MappingJacksonHttpMessageConverterTests { public class MappingJacksonHttpMessageConverterTests {
private MappingJacksonHttpMessageConverter converter; private MappingJacksonHttpMessageConverter converter;
@ -60,7 +62,7 @@ public class MappingJacksonHttpMessageConverterTests {
"{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}"; "{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
inputMessage.getHeaders().setContentType(new MediaType("application", "json")); inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
MyBean result = (MyBean) converter.read((Class) MyBean.class, inputMessage); MyBean result = (MyBean) converter.read(MyBean.class, inputMessage);
assertEquals("Foo", result.getString()); assertEquals("Foo", result.getString());
assertEquals(42, result.getNumber()); assertEquals(42, result.getNumber());
assertEquals(42F, result.getFraction(), 0F); assertEquals(42F, result.getFraction(), 0F);
@ -76,7 +78,7 @@ public class MappingJacksonHttpMessageConverterTests {
"{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}"; "{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
inputMessage.getHeaders().setContentType(new MediaType("application", "json")); inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
HashMap<String, Object> result = (HashMap<String, Object>) converter.read((Class)HashMap.class, inputMessage); HashMap<String, Object> result = (HashMap<String, Object>) converter.read(HashMap.class, inputMessage);
assertEquals("Foo", result.get("string")); assertEquals("Foo", result.get("string"));
assertEquals(42, result.get("number")); assertEquals(42, result.get("number"));
assertEquals(42D, (Double) result.get("fraction"), 0D); assertEquals(42D, (Double) result.get("fraction"), 0D);