diff options
Diffstat (limited to 'spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java')
-rw-r--r-- | spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java | 165 |
1 files changed, 159 insertions, 6 deletions
diff --git a/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java b/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java index b64abf2f..5d9bc44b 100644 --- a/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java +++ b/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJackson2MessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2016 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,12 +29,15 @@ import javax.jms.Message; import javax.jms.Session; import javax.jms.TextMessage; +import com.fasterxml.jackson.annotation.JsonView; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.ObjectWriter; import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.core.MethodParameter; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -50,14 +53,15 @@ import org.springframework.util.ClassUtils; * <li>{@link DeserializationFeature#FAIL_ON_UNKNOWN_PROPERTIES} is disabled</li> * </ul> * - * <p>Tested against Jackson 2.2; compatible with Jackson 2.0 and higher. + * <p>Compatible with Jackson 2.6 and higher, as of Spring 4.3. * * @author Mark Pollack * @author Dave Syer * @author Juergen Hoeller + * @author Stephane Nicoll * @since 3.1.4 */ -public class MappingJackson2MessageConverter implements MessageConverter, BeanClassLoaderAware { +public class MappingJackson2MessageConverter implements SmartMessageConverter, BeanClassLoaderAware { /** * The default encoding used for writing to text messages: UTF-8. @@ -190,6 +194,35 @@ public class MappingJackson2MessageConverter implements MessageConverter, BeanCl } @Override + public Message toMessage(Object object, Session session, Object conversionHint) + throws JMSException, MessageConversionException { + + return toMessage(object, session, getSerializationView(conversionHint)); + } + + /** + * Convert a Java object to a JMS Message using the specified json view + * and the supplied session to create the message object. + * @param object the object to convert + * @param session the Session to use for creating a JMS Message + * @param jsonView the view to use to filter the content + * @return the JMS Message + * @throws javax.jms.JMSException if thrown by JMS API methods + * @throws MessageConversionException in case of conversion failure + * @since 4.3 + */ + public Message toMessage(Object object, Session session, Class<?> jsonView) + throws JMSException, MessageConversionException { + + if (jsonView != null) { + return toMessage(object, session, this.objectMapper.writerWithView(jsonView)); + } + else { + return toMessage(object, session, this.objectMapper.writer()); + } + } + + @Override public Object fromMessage(Message message) throws JMSException, MessageConversionException { try { JavaType targetJavaType = getJavaTypeForMessage(message); @@ -200,6 +233,29 @@ public class MappingJackson2MessageConverter implements MessageConverter, BeanCl } } + protected Message toMessage(Object object, Session session, ObjectWriter objectWriter) + throws JMSException, MessageConversionException { + + Message message; + try { + switch (this.targetType) { + case TEXT: + message = mapToTextMessage(object, session, objectWriter); + break; + case BYTES: + message = mapToBytesMessage(object, session, objectWriter); + break; + default: + message = mapToMessage(object, session, objectWriter, this.targetType); + } + } + catch (IOException ex) { + throw new MessageConversionException("Could not map JSON object [" + object + "]", ex); + } + setTypeIdOnMessage(object, message); + return message; + } + /** * Map the given object to a {@link TextMessage}. @@ -210,12 +266,31 @@ public class MappingJackson2MessageConverter implements MessageConverter, BeanCl * @throws JMSException if thrown by JMS methods * @throws IOException in case of I/O errors * @see Session#createBytesMessage + * @deprecated as of 4.3, use {@link #mapToTextMessage(Object, Session, ObjectWriter)} */ + @Deprecated protected TextMessage mapToTextMessage(Object object, Session session, ObjectMapper objectMapper) throws JMSException, IOException { + return mapToTextMessage(object, session, objectMapper.writer()); + } + + /** + * Map the given object to a {@link TextMessage}. + * @param object the object to be mapped + * @param session current JMS session + * @param objectWriter the writer to use + * @return the resulting message + * @throws JMSException if thrown by JMS methods + * @throws IOException in case of I/O errors + * @see Session#createBytesMessage + * @since 4.3 + */ + protected TextMessage mapToTextMessage(Object object, Session session, ObjectWriter objectWriter) + throws JMSException, IOException { + StringWriter writer = new StringWriter(); - objectMapper.writeValue(writer, object); + objectWriter.writeValue(writer, object); return session.createTextMessage(writer.toString()); } @@ -228,13 +303,33 @@ public class MappingJackson2MessageConverter implements MessageConverter, BeanCl * @throws JMSException if thrown by JMS methods * @throws IOException in case of I/O errors * @see Session#createBytesMessage + * @deprecated as of 4.3, use {@link #mapToBytesMessage(Object, Session, ObjectWriter)} */ + @Deprecated protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper) throws JMSException, IOException { + return mapToBytesMessage(object, session, objectMapper.writer()); + } + + + /** + * Map the given object to a {@link BytesMessage}. + * @param object the object to be mapped + * @param session current JMS session + * @param objectWriter the writer to use + * @return the resulting message + * @throws JMSException if thrown by JMS methods + * @throws IOException in case of I/O errors + * @since 4.3 + * @see Session#createBytesMessage + */ + protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectWriter objectWriter) + throws JMSException, IOException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); OutputStreamWriter writer = new OutputStreamWriter(bos, this.encoding); - objectMapper.writeValue(writer, object); + objectWriter.writeValue(writer, object); BytesMessage message = session.createBytesMessage(); message.writeBytes(bos.toByteArray()); @@ -256,10 +351,31 @@ public class MappingJackson2MessageConverter implements MessageConverter, BeanCl * @return the resulting message * @throws JMSException if thrown by JMS methods * @throws IOException in case of I/O errors + * @deprecated as of 4.3, use {@link #mapToMessage(Object, Session, ObjectWriter, MessageType)} */ + @Deprecated protected Message mapToMessage(Object object, Session session, ObjectMapper objectMapper, MessageType targetType) throws JMSException, IOException { + return mapToMessage(object, session, objectMapper.writer(), targetType); + } + + /** + * Template method that allows for custom message mapping. + * Invoked when {@link #setTargetType} is not {@link MessageType#TEXT} or + * {@link MessageType#BYTES}. + * <p>The default implementation throws an {@link IllegalArgumentException}. + * @param object the object to marshal + * @param session the JMS Session + * @param objectWriter the writer to use + * @param targetType the target message type (other than TEXT or BYTES) + * @return the resulting message + * @throws JMSException if thrown by JMS methods + * @throws IOException in case of I/O errors + */ + protected Message mapToMessage(Object object, Session session, ObjectWriter objectWriter, MessageType targetType) + throws JMSException, IOException { + throw new IllegalArgumentException("Unsupported message type [" + targetType + "]. MappingJackson2MessageConverter by default only supports TextMessages and BytesMessages."); } @@ -286,7 +402,6 @@ public class MappingJackson2MessageConverter implements MessageConverter, BeanCl } } - /** * Convenience method to dispatch to converters for individual message types. */ @@ -391,4 +506,42 @@ public class MappingJackson2MessageConverter implements MessageConverter, BeanCl } } + /** + * Determine a Jackson serialization view based on the given conversion hint. + * @param conversionHint the conversion hint Object as passed into the + * converter for the current conversion attempt + * @return the serialization view class, or {@code null} if none + */ + protected Class<?> getSerializationView(Object conversionHint) { + if (conversionHint instanceof MethodParameter) { + MethodParameter methodParam = (MethodParameter) conversionHint; + JsonView annotation = methodParam.getParameterAnnotation(JsonView.class); + if (annotation == null) { + annotation = methodParam.getMethodAnnotation(JsonView.class); + if (annotation == null) { + return null; + } + } + return extractViewClass(annotation, conversionHint); + } + else if (conversionHint instanceof JsonView) { + return extractViewClass((JsonView) conversionHint, conversionHint); + } + else if (conversionHint instanceof Class) { + return (Class) conversionHint; + } + else { + return null; + } + } + + private Class<?> extractViewClass(JsonView annotation, Object conversionHint) { + Class<?>[] classes = annotation.value(); + if (classes.length != 1) { + throw new IllegalArgumentException( + "@JsonView only supported for handler methods with exactly 1 class argument: " + conversionHint); + } + return classes[0]; + } + } |