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 880ae9c75c0..dd3d4c04378 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-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -32,21 +32,22 @@ import javax.jms.TextMessage; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; +import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; /** * Message converter that uses the Jackson 2 library to convert messages to and from JSON. - * Maps an object to a {@link javax.jms.BytesMessage}, or to a {@link javax.jms.TextMessage} if the - * {@link #setTargetType targetType} is set to {@link org.springframework.jms.support.converter.MessageType#TEXT}. - * Converts from a {@link javax.jms.TextMessage} or {@link javax.jms.BytesMessage} to an object. + * Maps an object to a {@link BytesMessage}, or to a {@link TextMessage} if the + * {@link #setTargetType targetType} is set to {@link MessageType#TEXT}. + * Converts from a {@link TextMessage} or {@link BytesMessage} to an object. * * @author Mark Pollack * @author Dave Syer * @author Juergen Hoeller * @since 3.1.4 */ -public class MappingJackson2MessageConverter implements MessageConverter { +public class MappingJackson2MessageConverter implements MessageConverter, BeanClassLoaderAware { /** * The default encoding used for writing to text messages: UTF-8. @@ -68,9 +69,11 @@ public class MappingJackson2MessageConverter implements MessageConverter { private Map, String> classIdMappings = new HashMap, String>(); + private ClassLoader beanClassLoader; + /** - * Specify the {@link org.codehaus.jackson.map.ObjectMapper} to use instead of using the default. + * Specify the {@link ObjectMapper} to use instead of using the default. */ public void setObjectMapper(ObjectMapper objectMapper) { Assert.notNull(objectMapper, "ObjectMapper must not be null"); @@ -78,13 +81,13 @@ public class MappingJackson2MessageConverter implements MessageConverter { } /** - * Specify whether {@link #toMessage(Object, javax.jms.Session)} should marshal to a - * {@link javax.jms.BytesMessage} or a {@link javax.jms.TextMessage}. - *

The default is {@link org.springframework.jms.support.converter.MessageType#BYTES}, i.e. this converter marshals to - * a {@link javax.jms.BytesMessage}. Note that the default version of this converter - * supports {@link org.springframework.jms.support.converter.MessageType#BYTES} and {@link org.springframework.jms.support.converter.MessageType#TEXT} only. - * @see org.springframework.jms.support.converter.MessageType#BYTES - * @see org.springframework.jms.support.converter.MessageType#TEXT + * Specify whether {@link #toMessage(Object, Session)} should marshal to a + * {@link BytesMessage} or a {@link TextMessage}. + *

The default is {@link MessageType#BYTES}, i.e. this converter marshals to + * a {@link BytesMessage}. Note that the default version of this converter + * supports {@link MessageType#BYTES} and {@link MessageType#TEXT} only. + * @see MessageType#BYTES + * @see MessageType#TEXT */ public void setTargetType(MessageType targetType) { Assert.notNull(targetType, "MessageType must not be null"); @@ -142,6 +145,10 @@ public class MappingJackson2MessageConverter implements MessageConverter { } } + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + } + public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException { Message message; @@ -176,15 +183,14 @@ public class MappingJackson2MessageConverter implements MessageConverter { /** - * Map the given object to a {@link javax.jms.TextMessage}. + * Map the given object to a {@link TextMessage}. * @param object the object to be mapped * @param session current JMS session * @param objectMapper the mapper to use * @return the resulting message - * @throws javax.jms.JMSException if thrown by JMS methods - * @throws java.io.IOException in case of I/O errors - * @see javax.jms.Session#createBytesMessage - * @see org.springframework.oxm.Marshaller#marshal(Object, javax.xml.transform.Result) + * @throws JMSException if thrown by JMS methods + * @throws IOException in case of I/O errors + * @see Session#createBytesMessage */ protected TextMessage mapToTextMessage(Object object, Session session, ObjectMapper objectMapper) throws JMSException, IOException { @@ -195,15 +201,14 @@ public class MappingJackson2MessageConverter implements MessageConverter { } /** - * Map the given object to a {@link javax.jms.BytesMessage}. + * Map the given object to a {@link BytesMessage}. * @param object the object to be mapped * @param session current JMS session * @param objectMapper the mapper to use * @return the resulting message - * @throws javax.jms.JMSException if thrown by JMS methods - * @throws java.io.IOException in case of I/O errors - * @see javax.jms.Session#createBytesMessage - * @see org.springframework.oxm.Marshaller#marshal(Object, javax.xml.transform.Result) + * @throws JMSException if thrown by JMS methods + * @throws IOException in case of I/O errors + * @see Session#createBytesMessage */ protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper) throws JMSException, IOException { @@ -222,22 +227,22 @@ public class MappingJackson2MessageConverter implements MessageConverter { /** * Template method that allows for custom message mapping. - * Invoked when {@link #setTargetType} is not {@link org.springframework.jms.support.converter.MessageType#TEXT} or - * {@link org.springframework.jms.support.converter.MessageType#BYTES}. + * Invoked when {@link #setTargetType} is not {@link MessageType#TEXT} or + * {@link MessageType#BYTES}. *

The default implementation throws an {@link IllegalArgumentException}. * @param object the object to marshal * @param session the JMS Session * @param objectMapper the mapper to use * @param targetType the target message type (other than TEXT or BYTES) * @return the resulting message - * @throws javax.jms.JMSException if thrown by JMS methods - * @throws java.io.IOException in case of I/O errors + * @throws JMSException if thrown by JMS methods + * @throws IOException in case of I/O errors */ protected Message mapToMessage(Object object, Session session, ObjectMapper objectMapper, MessageType targetType) throws JMSException, IOException { throw new IllegalArgumentException("Unsupported message type [" + targetType + - "]. MappingJacksonMessageConverter by default only supports TextMessages and BytesMessages."); + "]. MappingJackson2MessageConverter by default only supports TextMessages and BytesMessages."); } /** @@ -247,7 +252,7 @@ public class MappingJackson2MessageConverter implements MessageConverter { * into the configured type id message property. * @param object the payload object to set a type id for * @param message the JMS Message to set the type id on - * @throws javax.jms.JMSException if thrown by JMS methods + * @throws JMSException if thrown by JMS methods * @see #getJavaTypeForMessage(javax.jms.Message) * @see #setTypeIdPropertyName(String) * @see #setTypeIdMappings(java.util.Map) @@ -283,8 +288,8 @@ public class MappingJackson2MessageConverter implements MessageConverter { * @param message the input message * @param targetJavaType the target type * @return the message converted to an object - * @throws javax.jms.JMSException if thrown by JMS - * @throws java.io.IOException in case of I/O errors + * @throws JMSException if thrown by JMS + * @throws IOException in case of I/O errors */ protected Object convertFromTextMessage(TextMessage message, JavaType targetJavaType) throws JMSException, IOException { @@ -298,8 +303,8 @@ public class MappingJackson2MessageConverter implements MessageConverter { * @param message the input message * @param targetJavaType the target type * @return the message converted to an object - * @throws javax.jms.JMSException if thrown by JMS - * @throws java.io.IOException in case of I/O errors + * @throws JMSException if thrown by JMS + * @throws IOException in case of I/O errors */ protected Object convertFromBytesMessage(BytesMessage message, JavaType targetJavaType) throws JMSException, IOException { @@ -321,14 +326,14 @@ public class MappingJackson2MessageConverter implements MessageConverter { /** * Template method that allows for custom message mapping. - * Invoked when {@link #setTargetType} is not {@link org.springframework.jms.support.converter.MessageType#TEXT} or - * {@link org.springframework.jms.support.converter.MessageType#BYTES}. + * Invoked when {@link #setTargetType} is not {@link MessageType#TEXT} or + * {@link MessageType#BYTES}. *

The default implementation throws an {@link IllegalArgumentException}. * @param message the input message * @param targetJavaType the target type * @return the message converted to an object - * @throws javax.jms.JMSException if thrown by JMS - * @throws java.io.IOException in case of I/O errors + * @throws JMSException if thrown by JMS + * @throws IOException in case of I/O errors */ protected Object convertFromMessage(Message message, JavaType targetJavaType) throws JMSException, IOException { @@ -344,7 +349,7 @@ public class MappingJackson2MessageConverter implements MessageConverter { * and consults the configured type id mapping. This can be overridden with * a different strategy, e.g. doing some heuristics based on message origin. * @param message the JMS Message to set the type id on - * @throws javax.jms.JMSException if thrown by JMS methods + * @throws JMSException if thrown by JMS methods * @see #setTypeIdOnMessage(Object, javax.jms.Message) * @see #setTypeIdPropertyName(String) * @see #setTypeIdMappings(java.util.Map) @@ -354,13 +359,13 @@ public class MappingJackson2MessageConverter implements MessageConverter { if (typeId == null) { throw new MessageConversionException("Could not find type id property [" + this.typeIdPropertyName + "]"); } - Class mappedClass = this.idClassMappings.get(typeId); + Class mappedClass = this.idClassMappings.get(typeId); if (mappedClass != null) { return this.objectMapper.getTypeFactory().constructType(mappedClass); } try { - return this.objectMapper.getTypeFactory().constructType( - ClassUtils.forName(typeId, getClass().getClassLoader())); + Class typeClass = ClassUtils.forName(typeId, this.beanClassLoader); + return this.objectMapper.getTypeFactory().constructType(typeClass); } catch (Throwable ex) { throw new MessageConversionException("Failed to resolve type id [" + typeId + "]", ex); diff --git a/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJacksonMessageConverter.java b/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJacksonMessageConverter.java index 091e5fc4a33..96812a4d1be 100644 --- a/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJacksonMessageConverter.java +++ b/spring-jms/src/main/java/org/springframework/jms/support/converter/MappingJacksonMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2013 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. @@ -28,13 +28,12 @@ import javax.jms.JMSException; import javax.jms.Message; import javax.jms.Session; import javax.jms.TextMessage; -import javax.xml.transform.Result; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.type.TypeFactory; import org.codehaus.jackson.type.JavaType; -import org.springframework.oxm.Marshaller; +import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; @@ -49,7 +48,7 @@ import org.springframework.util.ClassUtils; * @author Juergen Hoeller * @since 3.1 */ -public class MappingJacksonMessageConverter implements MessageConverter { +public class MappingJacksonMessageConverter implements MessageConverter, BeanClassLoaderAware { /** * The default encoding used for writing to text messages: UTF-8. @@ -71,6 +70,8 @@ public class MappingJacksonMessageConverter implements MessageConverter { private Map, String> classIdMappings = new HashMap, String>(); + private ClassLoader beanClassLoader; + /** * Specify the {@link ObjectMapper} to use instead of using the default. @@ -145,6 +146,10 @@ public class MappingJacksonMessageConverter implements MessageConverter { } } + public void setBeanClassLoader(ClassLoader classLoader) { + this.beanClassLoader = classLoader; + } + public Message toMessage(Object object, Session session) throws JMSException, MessageConversionException { Message message; @@ -187,7 +192,6 @@ public class MappingJacksonMessageConverter implements MessageConverter { * @throws JMSException if thrown by JMS methods * @throws IOException in case of I/O errors * @see Session#createBytesMessage - * @see Marshaller#marshal(Object, Result) */ protected TextMessage mapToTextMessage(Object object, Session session, ObjectMapper objectMapper) throws JMSException, IOException { @@ -206,7 +210,6 @@ public class MappingJacksonMessageConverter implements MessageConverter { * @throws JMSException if thrown by JMS methods * @throws IOException in case of I/O errors * @see Session#createBytesMessage - * @see Marshaller#marshal(Object, Result) */ protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper) throws JMSException, IOException { @@ -357,12 +360,13 @@ public class MappingJacksonMessageConverter implements MessageConverter { if (typeId == null) { throw new MessageConversionException("Could not find type id property [" + this.typeIdPropertyName + "]"); } - Class mappedClass = this.idClassMappings.get(typeId); + Class mappedClass = this.idClassMappings.get(typeId); if (mappedClass != null) { return TypeFactory.type(mappedClass); } try { - return TypeFactory.type(ClassUtils.forName(typeId, getClass().getClassLoader())); + Class typeClass = ClassUtils.forName(typeId, this.beanClassLoader); + return TypeFactory.type(typeClass); } catch (Throwable ex) { throw new MessageConversionException("Failed to resolve type id [" + typeId + "]", ex);