From df6d360441ca7e22152c880e0b3662dc339526ff Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Sun, 17 Oct 2010 16:03:09 -0400 Subject: [PATCH] INT-1000 polishing JsonInboundMessageMapper --- ...per.java => JsonInboundMessageMapper.java} | 57 ++++++++++--------- ...ava => JsonInboundMessageMapperTests.java} | 36 ++++++------ 2 files changed, 50 insertions(+), 43 deletions(-) rename spring-integration-core/src/main/java/org/springframework/integration/json/{InboundJsonMessageMapper.java => JsonInboundMessageMapper.java} (79%) rename spring-integration-core/src/test/java/org/springframework/integration/json/{InboundJsonMessageMapperTests.java => JsonInboundMessageMapperTests.java} (90%) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/json/InboundJsonMessageMapper.java b/spring-integration-core/src/main/java/org/springframework/integration/json/JsonInboundMessageMapper.java similarity index 79% rename from spring-integration-core/src/main/java/org/springframework/integration/json/InboundJsonMessageMapper.java rename to spring-integration-core/src/main/java/org/springframework/integration/json/JsonInboundMessageMapper.java index 7b5d2df31e..cedd59d4f2 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/json/InboundJsonMessageMapper.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/json/JsonInboundMessageMapper.java @@ -38,42 +38,41 @@ import org.springframework.util.Assert; /** * {@link InboundMessageMapper} implementation that maps incoming JSON messages to a {@link Message} with the specified payload type. * - * TODO - Need to figure out if we need to go as deep in mapping HeaderTypes...right now it wouldn't work if the header type was something like List - * - cannot assume order as implemented; headers may not always precede the payload - * * @author Jeremy Grelle * @since 2.0 */ -public class InboundJsonMessageMapper implements - InboundMessageMapper { +public class JsonInboundMessageMapper implements InboundMessageMapper { private static final String MESSAGE_FORMAT_ERROR = "JSON message is invalid. Expected a message in the format of {\"headers\":{...},\"payload\":{...}} but was "; - - private ObjectMapper objectMapper = new ObjectMapper(); private static Map> DEFAULT_HEADER_TYPES; - - private Map> headerTypes = DEFAULT_HEADER_TYPES; - private boolean mapToPayload = false; - - private JavaType payloadType; - static { DEFAULT_HEADER_TYPES = new HashMap>(); DEFAULT_HEADER_TYPES.put(MessageHeaders.ID, UUID.class); DEFAULT_HEADER_TYPES.put(MessageHeaders.TIMESTAMP, Long.class); DEFAULT_HEADER_TYPES.put(MessageHeaders.EXPIRATION_DATE, Long.class); } - - public InboundJsonMessageMapper(Class payloadType) { + + + private final ObjectMapper objectMapper = new ObjectMapper(); + + private final JavaType payloadType; + + private final Map> headerTypes = DEFAULT_HEADER_TYPES; + + private volatile boolean mapToPayload = false; + + + public JsonInboundMessageMapper(Class payloadType) { this.payloadType = TypeFactory.type(payloadType); } - - public InboundJsonMessageMapper(TypeReference typeReference) { + + public JsonInboundMessageMapper(TypeReference typeReference) { this.payloadType = TypeFactory.type(typeReference); } - + + public void setHeaderTypes(Map> headerTypes) { this.headerTypes.putAll(headerTypes); } @@ -84,14 +83,16 @@ public class InboundJsonMessageMapper implements public Message toMessage(String jsonMessage) throws Exception { JsonParser parser = new JsonFactory().createJsonParser(jsonMessage); - if (mapToPayload) { + if (this.mapToPayload) { try { Object payload = objectMapper.readValue(parser, payloadType); return MessageBuilder.withPayload(payload).build(); - } catch (JsonMappingException ex) { + } + catch (JsonMappingException ex) { throw new IllegalArgumentException("Mapping of JSON message "+jsonMessage+" directly to payload of type "+payloadType.getRawClass().getName()+" failed.", ex); } - } else { + } + else { String error = MESSAGE_FORMAT_ERROR + jsonMessage; Assert.isTrue(parser.nextToken() == JsonToken.START_OBJECT, error); Assert.isTrue(parser.nextToken() == JsonToken.FIELD_NAME, error); @@ -101,10 +102,12 @@ public class InboundJsonMessageMapper implements while (parser.nextToken() != JsonToken.END_OBJECT) { String headerName = parser.getCurrentName(); parser.nextToken(); - Class headerType = headerTypes.containsKey(headerName) ? headerTypes.get(headerName) : Object.class; + Class headerType = this.headerTypes.containsKey(headerName) ? + this.headerTypes.get(headerName) : Object.class; try { - headers.put(headerName, objectMapper.readValue(parser, headerType)); - } catch (JsonMappingException ex) { + headers.put(headerName, this.objectMapper.readValue(parser, headerType)); + } + catch (JsonMappingException ex) { throw new IllegalArgumentException("Mapping header \""+headerName+"\" of JSON message "+jsonMessage+" to header type "+payloadType.getRawClass().getName()+" failed.", ex); } } @@ -112,11 +115,13 @@ public class InboundJsonMessageMapper implements Assert.isTrue(parser.getCurrentName().equals("payload"), error); parser.nextToken(); try { - Object payload = objectMapper.readValue(parser, payloadType); + Object payload = this.objectMapper.readValue(parser, this.payloadType); return MessageBuilder.withPayload(payload).copyHeaders(headers).build(); - } catch (JsonMappingException ex) { + } + catch (JsonMappingException ex) { throw new IllegalArgumentException("Mapping payload of JSON message "+jsonMessage+" to payload type "+payloadType.getRawClass().getName()+" failed.", ex); } } } + } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/json/InboundJsonMessageMapperTests.java b/spring-integration-core/src/test/java/org/springframework/integration/json/JsonInboundMessageMapperTests.java similarity index 90% rename from spring-integration-core/src/test/java/org/springframework/integration/json/InboundJsonMessageMapperTests.java rename to spring-integration-core/src/test/java/org/springframework/integration/json/JsonInboundMessageMapperTests.java index 802d9e1e7f..45121314fb 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/json/InboundJsonMessageMapperTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/json/JsonInboundMessageMapperTests.java @@ -45,21 +45,23 @@ import org.springframework.integration.support.MessageBuilder; * @author Mark Fisher * @author Dave Syer */ -public class InboundJsonMessageMapperTests { +public class JsonInboundMessageMapperTests { private ObjectMapper mapper = new ObjectMapper(); - + + @Factory public static Matcher> sameExceptImmutableHeaders(Message operand) { return new MessageMatcher(operand); } + @Test public void testToMessageWithHeadersAndStringPayload() throws Exception { UUID id = UUID.randomUUID(); String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":\"myPayloadStuff\"}"; Message expected = MessageBuilder.withPayload("myPayloadStuff").setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).build(); - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(String.class); Message result = mapper.toMessage(jsonMessage); assertThat(result, sameExceptImmutableHeaders(expected)); } @@ -68,7 +70,7 @@ public class InboundJsonMessageMapperTests { public void testToMessageWithStringPayload() throws Exception { String jsonMessage = "\"myPayloadStuff\""; String expected = "myPayloadStuff"; - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(String.class); mapper.setMapToPayload(true); Message result = mapper.toMessage(jsonMessage); assertEquals(expected, result.getPayload()); @@ -80,7 +82,7 @@ public class InboundJsonMessageMapperTests { UUID id = UUID.randomUUID(); String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":" + getBeanAsJson(bean) + "}"; Message expected = MessageBuilder.withPayload(bean).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).build(); - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(TestBean.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(TestBean.class); Message result = mapper.toMessage(jsonMessage); assertThat(result, sameExceptImmutableHeaders(expected)); } @@ -89,7 +91,7 @@ public class InboundJsonMessageMapperTests { public void testToMessageWithBeanPayload() throws Exception { TestBean expected = new TestBean(); String jsonMessage = getBeanAsJson(expected); - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(TestBean.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(TestBean.class); mapper.setMapToPayload(true); Message result = mapper.toMessage(jsonMessage); assertEquals(expected, result.getPayload()); @@ -102,7 +104,7 @@ public class InboundJsonMessageMapperTests { String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\", \"myHeader\":" + getBeanAsJson(bean) + "},\"payload\":\"myPayloadStuff\"}"; Message expected = MessageBuilder.withPayload("myPayloadStuff"). setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).setHeader("myHeader", bean).build(); - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(String.class); Map> headerTypes = new HashMap>(); headerTypes.put("myHeader", TestBean.class); mapper.setHeaderTypes(headerTypes); @@ -116,7 +118,7 @@ public class InboundJsonMessageMapperTests { String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":[\"myPayloadStuff1\",\"myPayloadStuff2\",\"myPayloadStuff3\"]}"; List expectedList = Arrays.asList(new String[]{"myPayloadStuff1", "myPayloadStuff2", "myPayloadStuff3"}); Message> expected = MessageBuilder.withPayload(expectedList).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).build(); - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(new TypeReference>(){}); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(new TypeReference>(){}); Message result = mapper.toMessage(jsonMessage); assertThat(result, sameExceptImmutableHeaders(expected)); } @@ -129,16 +131,16 @@ public class InboundJsonMessageMapperTests { String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":[" + getBeanAsJson(bean1) + "," + getBeanAsJson(bean2) + "]}"; List expectedList = Arrays.asList(new TestBean[]{bean1, bean2}); Message> expected = MessageBuilder.withPayload(expectedList).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).build(); - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(new TypeReference>(){}); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(new TypeReference>(){}); Message result = mapper.toMessage(jsonMessage); assertThat(result, sameExceptImmutableHeaders(expected)); } - + @Test public void testToMessageInvalidFormatPayloadAndHeadersReversed() throws Exception { UUID id = UUID.randomUUID(); String jsonMessage = "{\"payload\":\"myPayloadStuff\",\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"}}"; - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(String.class); try { mapper.toMessage(jsonMessage); fail(); @@ -151,7 +153,7 @@ public class InboundJsonMessageMapperTests { @Test public void testToMessageInvalidFormatPayloadNoHeaders() throws Exception { String jsonMessage = "{\"payload\":\"myPayloadStuff\"}"; - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(String.class); try { mapper.toMessage(jsonMessage); fail(); @@ -165,7 +167,7 @@ public class InboundJsonMessageMapperTests { public void testToMessageInvalidFormatHeadersNoPayload() throws Exception { UUID id = UUID.randomUUID(); String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"}}"; - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(String.class); try { mapper.toMessage(jsonMessage); fail(); @@ -179,7 +181,7 @@ public class InboundJsonMessageMapperTests { public void testToMessageInvalidFormatHeadersAndStringPayloadWithMapToPayload() throws Exception { UUID id = UUID.randomUUID(); String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":\"myPayloadStuff\"}"; - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(String.class); mapper.setMapToPayload(true); try { mapper.toMessage(jsonMessage); @@ -195,7 +197,7 @@ public class InboundJsonMessageMapperTests { TestBean bean = new TestBean(); UUID id = UUID.randomUUID(); String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":" + getBeanAsJson(bean) + "}"; - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(TestBean.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(TestBean.class); mapper.setMapToPayload(true); try { mapper.toMessage(jsonMessage); @@ -211,7 +213,7 @@ public class InboundJsonMessageMapperTests { TestBean bean = new TestBean(); UUID id = UUID.randomUUID(); String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":" + getBeanAsJson(bean) + "}"; - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(Long.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(Long.class); try { mapper.toMessage(jsonMessage); fail(); @@ -226,7 +228,7 @@ public class InboundJsonMessageMapperTests { TestBean bean = new TestBean(); UUID id = UUID.randomUUID(); String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\",\"myHeader\":" + getBeanAsJson(bean) + "},\"payload\":\"myPayloadStuff\"}"; - InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); + JsonInboundMessageMapper mapper = new JsonInboundMessageMapper(String.class); Map> headerTypes = new HashMap>(); headerTypes.put("myHeader", Long.class); mapper.setHeaderTypes(headerTypes);