diff --git a/spring-amqp-core/src/main/java/org/springframework/amqp/support/converter/JsonMessageConverter.java b/spring-amqp-core/src/main/java/org/springframework/amqp/support/converter/JsonMessageConverter.java index d971a3c9..a566c485 100644 --- a/spring-amqp-core/src/main/java/org/springframework/amqp/support/converter/JsonMessageConverter.java +++ b/spring-amqp-core/src/main/java/org/springframework/amqp/support/converter/JsonMessageConverter.java @@ -1,17 +1,14 @@ /* * Copyright 2002-2010 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. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under 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 obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. */ package org.springframework.amqp.support.converter; @@ -34,20 +31,20 @@ import org.springframework.amqp.core.MessageProperties; * * @author Mark Pollack * @author James Carr + * @author Dave Syer */ public class JsonMessageConverter implements MessageConverter { - // TODO create composite MessageConverter with key/value pairs of content-type/converter. introduce base class - + // TODO create composite MessageConverter with key/value pairs of content-type/converter. introduce base class + private static Log log = LogFactory.getLog(JsonMessageConverter.class); public static final String DEFAULT_CHARSET = "UTF-8"; - private volatile String defaultCharset = DEFAULT_CHARSET; - + private ObjectMapper jsonObjectMapper = new ObjectMapper(); - + private ClassMapper classMapper = new DefaultClassMapper(); public JsonMessageConverter() { @@ -56,8 +53,8 @@ public class JsonMessageConverter implements MessageConverter { } /** - * Specify the default charset to use when converting to or from text-based - * Message body content. If not specified, the charset will be "UTF-8". + * Specify the default charset to use when converting to or from text-based Message body content. If not specified, + * the charset will be "UTF-8". */ public void setDefaultCharset(String defaultCharset) { this.defaultCharset = (defaultCharset != null) ? defaultCharset : DEFAULT_CHARSET; @@ -71,6 +68,16 @@ public class JsonMessageConverter implements MessageConverter { this.classMapper = classMapper; } + /** + * The {@link ObjectMapper} to use instead of using the default. An alternative to injecting a mapper is to extend + * this class and override {@link #initializeJsonObjectMapper()}. + * + * @param jsonObjectMapper the object mapper to set + */ + public void setJsonObjectMapper(ObjectMapper jsonObjectMapper) { + this.jsonObjectMapper = jsonObjectMapper; + } + /** * Subclass and override to customize. */ @@ -78,10 +85,9 @@ public class JsonMessageConverter implements MessageConverter { jsonObjectMapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); } - public Object fromMessage(Message message) throws MessageConversionException { Object content = null; - MessageProperties properties = message.getMessageProperties(); + MessageProperties properties = message.getMessageProperties(); if (properties != null) { String contentType = properties.getContentType(); if (contentType != null && contentType.contains("json")) { @@ -90,25 +96,20 @@ public class JsonMessageConverter implements MessageConverter { encoding = this.defaultCharset; } try { - //content = new String(message.getBody(), encoding); - + // content = new String(message.getBody(), encoding); + Class targetClass = classMapper.toClass(message.getMessageProperties()); content = convertBytesToObject(message.getBody(), encoding, targetClass); - } - catch (UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException e) { throw new MessageConversionException("Failed to convert json-based Message content", e); - } - catch (JsonParseException e) { + } catch (JsonParseException e) { + throw new MessageConversionException("Failed to convert Message content", e); + } catch (JsonMappingException e) { + throw new MessageConversionException("Failed to convert Message content", e); + } catch (IOException e) { throw new MessageConversionException("Failed to convert Message content", e); } - catch (JsonMappingException e) { - throw new MessageConversionException("Failed to convert Message content", e); - } - catch (IOException e) { - throw new MessageConversionException("Failed to convert Message content", e); - } - } - else { + } else { log.warn("Could not convert incoming message with content-type [" + contentType + "]"); } } @@ -118,27 +119,25 @@ public class JsonMessageConverter implements MessageConverter { return content; } - - private Object convertBytesToObject(byte[] body, String encoding, Class targetClass) throws JsonParseException, JsonMappingException, IOException { + private Object convertBytesToObject(byte[] body, String encoding, Class targetClass) throws JsonParseException, + JsonMappingException, IOException { String contentAsString = new String(body, encoding); - return jsonObjectMapper.readValue(contentAsString, targetClass); + return jsonObjectMapper.readValue(contentAsString, targetClass); } - public Message toMessage(Object objectToConvert, MessageProperties messageProperties) throws MessageConversionException { + + public Message toMessage(Object objectToConvert, MessageProperties messageProperties) + throws MessageConversionException { byte[] bytes = null; try { String jsonString = jsonObjectMapper.writeValueAsString(objectToConvert); bytes = jsonString.getBytes(this.defaultCharset); - } - catch (UnsupportedEncodingException e) { + } catch (UnsupportedEncodingException e) { throw new MessageConversionException("Failed to convert Message content", e); - } - catch (JsonGenerationException e) { + } catch (JsonGenerationException e) { throw new MessageConversionException("Failed to convert Message content", e); - } - catch (JsonMappingException e) { + } catch (JsonMappingException e) { throw new MessageConversionException("Failed to convert Message content", e); - } - catch (IOException e) { + } catch (IOException e) { throw new MessageConversionException("Failed to convert Message content", e); } messageProperties.setContentType(MessageProperties.CONTENT_TYPE_JSON); diff --git a/spring-amqp-core/src/test/java/org/springframework/amqp/support/converter/JsonMessageConverterTests.java b/spring-amqp-core/src/test/java/org/springframework/amqp/support/converter/JsonMessageConverterTests.java index eb573a41..502f5d01 100644 --- a/spring-amqp-core/src/test/java/org/springframework/amqp/support/converter/JsonMessageConverterTests.java +++ b/spring-amqp-core/src/test/java/org/springframework/amqp/support/converter/JsonMessageConverterTests.java @@ -18,12 +18,15 @@ import static org.junit.Assert.assertEquals; import java.math.BigDecimal; import java.util.Hashtable; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.ser.BeanSerializerFactory; import org.junit.Test; import org.springframework.amqp.core.Message; import org.springframework.amqp.core.MessageProperties; /** * @author Mark Pollack + * @author Dave Syer */ public class JsonMessageConverterTests { @@ -45,6 +48,27 @@ public class JsonMessageConverterTests { assertEquals(trade, marshalledTrade); } + @Test + public void simpleTradeOverrideMapper() { + SimpleTrade trade = new SimpleTrade(); + trade.setAccountName("Acct1"); + trade.setBuyRequest(true); + trade.setOrderType("Market"); + trade.setPrice(new BigDecimal(103.30)); + trade.setQuantity(100); + trade.setRequestId("R123"); + trade.setTicker("VMW"); + trade.setUserName("Joe Trader"); + JsonMessageConverter converter = new JsonMessageConverter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializerFactory(BeanSerializerFactory.instance); + converter.setJsonObjectMapper(mapper); + Message message = converter.toMessage(trade, new MessageProperties()); + + SimpleTrade marshalledTrade = (SimpleTrade) converter.fromMessage(message); + assertEquals(trade, marshalledTrade); + } + @Test public void nestedBean() { Bar bar = new Bar();