From bde0bca24e0ef9c2b6284594882473fa0c9b7504 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Mon, 29 Mar 2010 17:20:28 +0000 Subject: [PATCH] INT-1053 Message ID is now always a UUID rather than any Object type --- .../integration/core/MessageHeaders.java | 10 +- .../json/InboundJsonMessageMapper.java | 2 + .../CorrelatingMessageHandlerTests.java | 70 +++++++----- .../gateway/SimpleMessagingGatewayTests.java | 12 +- .../json/InboundJsonMessageMapperTests.java | 106 ++++++++++++------ 5 files changed, 129 insertions(+), 71 deletions(-) diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/core/MessageHeaders.java b/org.springframework.integration/src/main/java/org/springframework/integration/core/MessageHeaders.java index 0d307ab00f..5b4fe998cf 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/core/MessageHeaders.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/core/MessageHeaders.java @@ -31,6 +31,7 @@ import java.util.UUID; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; + import org.springframework.integration.history.MessageHistory; /** @@ -45,6 +46,11 @@ public final class MessageHeaders implements Map, Serializable { public static final String PREFIX = "$"; + /** + * The key for the Message ID. This is an automatically generated UUID and should + * never be explicitly set in the header map except in the case of Message + * deserialization where the serialized Message's generated UUID is being restored. + */ public static final String ID = PREFIX + "id"; public static final String TIMESTAMP = PREFIX + "timestamp"; @@ -85,8 +91,8 @@ public final class MessageHeaders implements Map, Serializable { } - public Object getId() { - return this.get(ID); + public UUID getId() { + return this.get(ID, UUID.class); } public Long getTimestamp() { diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/json/InboundJsonMessageMapper.java b/org.springframework.integration/src/main/java/org/springframework/integration/json/InboundJsonMessageMapper.java index cad673b7fa..4434c2f9e6 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/json/InboundJsonMessageMapper.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/json/InboundJsonMessageMapper.java @@ -19,6 +19,7 @@ package org.springframework.integration.json; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; +import java.util.UUID; import org.codehaus.jackson.JsonFactory; import org.codehaus.jackson.JsonParser; @@ -60,6 +61,7 @@ public class InboundJsonMessageMapper implements 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); } diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/aggregator/CorrelatingMessageHandlerTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/aggregator/CorrelatingMessageHandlerTests.java index 063d9c7eab..2bfe546982 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/aggregator/CorrelatingMessageHandlerTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/aggregator/CorrelatingMessageHandlerTests.java @@ -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"); * you may not use this file except in compliance with the License. @@ -16,6 +16,21 @@ package org.springframework.integration.aggregator; +import static org.junit.Assert.assertFalse; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Executors; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -23,6 +38,7 @@ import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; + import org.springframework.integration.channel.MessageChannelTemplate; import org.springframework.integration.core.Message; import org.springframework.integration.core.MessageChannel; @@ -30,17 +46,6 @@ import org.springframework.integration.core.MessageHeaders; import org.springframework.integration.message.MessageBuilder; import org.springframework.integration.store.MessageStore; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Executors; - -import static org.junit.Assert.assertFalse; -import static org.mockito.Matchers.eq; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.*; - /** * @author Iwein Fuld */ @@ -69,7 +74,7 @@ public class CorrelatingMessageHandlerTests { handler = new CorrelatingMessageHandler( store, correlationStrategy, completionStrategy, processor); handler.setOutputChannel(outputChannel); - doAnswer(new Answer() { + doAnswer(new Answer() { public Object answer(InvocationOnMock invocation) throws Throwable { MessageGroup messageGroup = (MessageGroup) invocation.getArguments()[0]; messageGroup.onProcessingOf(messageGroup.getMessages().toArray(new Message[2])); @@ -83,8 +88,10 @@ public class CorrelatingMessageHandlerTests { @Test public void bufferCompletesNormally() throws Exception { String correlationKey = "key"; - Message message1 = testMessage(correlationKey, 1, 1); - Message message2 = testMessage(correlationKey, 2, 2); + UUID id1 = UUID.randomUUID(); + UUID id2 = UUID.randomUUID(); + Message message1 = testMessage(correlationKey, id1, 1); + Message message2 = testMessage(correlationKey, id2, 2); List> storedMessages = new ArrayList>(); when(store.list(correlationKey)).thenReturn(storedMessages); @@ -92,12 +99,12 @@ public class CorrelatingMessageHandlerTests { when(correlationStrategy.getCorrelationKey(isA(Message.class))) .thenReturn(correlationKey); - when(completionStrategy.isComplete(Arrays.asList(message1))).thenReturn(false); + when(completionStrategy.isComplete(Arrays.>asList(message1))).thenReturn(false); handler.handleMessage(message1); storedMessages.add(message1); - when(completionStrategy.isComplete(Arrays.asList(message1, message2))).thenReturn(true); + when(completionStrategy.isComplete(Arrays.>asList(message1, message2))).thenReturn(true); handler.handleMessage(message2); storedMessages.add(message2); @@ -106,8 +113,8 @@ public class CorrelatingMessageHandlerTests { verify(store, times(2)).list(correlationKey); verify(correlationStrategy).getCorrelationKey(message1); verify(correlationStrategy).getCorrelationKey(message2); - verify(completionStrategy).isComplete(Arrays.asList(message1)); - verify(completionStrategy).isComplete(Arrays.asList(message1, message2)); + verify(completionStrategy).isComplete(Arrays.>asList(message1)); + verify(completionStrategy).isComplete(Arrays.>asList(message1, message2)); verify(processor).processAndSend(isA(MessageGroup.class), isA(MessageChannelTemplate.class), eq(outputChannel) ); @@ -121,8 +128,10 @@ public class CorrelatingMessageHandlerTests { @Test public void shouldNotPruneWhileCompleting() throws Exception { String correlationKey = "key"; - final Message message1 = testMessage(correlationKey, 1, 1); - final Message message2 = testMessage(correlationKey, 2, 2); + UUID id1 = UUID.randomUUID(); + UUID id2 = UUID.randomUUID(); + final Message message1 = testMessage(correlationKey, id1, 1); + final Message message2 = testMessage(correlationKey, id2, 2); final List> storedMessages = new ArrayList>(); final CountDownLatch bothMessagesHandled = new CountDownLatch(2); @@ -132,12 +141,13 @@ public class CorrelatingMessageHandlerTests { when(correlationStrategy.getCorrelationKey(isA(Message.class))) .thenReturn(correlationKey); - when(completionStrategy.isComplete(Arrays.asList(message1, message2))).thenAnswer(new Answer() { - public Boolean answer(InvocationOnMock invocation) throws Throwable { - Thread.sleep(50); - return true; - } - }).thenReturn(true); + when(completionStrategy.isComplete(Arrays.>asList(message1, message2))) + .thenAnswer(new Answer() { + public Boolean answer(InvocationOnMock invocation) throws Throwable { + Thread.sleep(50); + return true; + } + }).thenReturn(true); handler.handleMessage(message1); bothMessagesHandled.countDown(); @@ -156,11 +166,11 @@ public class CorrelatingMessageHandlerTests { bothMessagesHandled.await(); verify(store).put(message1); verify(store).put(message2); - verify(store).delete(1); - verify(store).delete(2); + verify(store).delete(id1); + verify(store).delete(id2); } - private Message testMessage(String correllationKey, int id, int sequenceNumber) { + private Message testMessage(String correllationKey, UUID id, int sequenceNumber) { return MessageBuilder.withPayload("test" + id) .setHeader(MessageHeaders.ID, id) .setCorrelationId(correllationKey) diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/gateway/SimpleMessagingGatewayTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/gateway/SimpleMessagingGatewayTests.java index 7b67e33c1e..f4a42a7ce9 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/gateway/SimpleMessagingGatewayTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/gateway/SimpleMessagingGatewayTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2008 the original author or authors. + * 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. @@ -17,12 +17,16 @@ package org.springframework.integration.gateway; import static org.easymock.EasyMock.*; -import org.easymock.IAnswer; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; + +import java.util.UUID; + +import org.easymock.IAnswer; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; + import org.springframework.integration.channel.PollableChannel; import org.springframework.integration.core.Message; import org.springframework.integration.core.MessageChannel; @@ -152,7 +156,7 @@ public class SimpleMessagingGatewayTests { expect(replyChannel.getName()).andReturn("replyChannel").anyTimes(); expect(messageMock.getHeaders()).andReturn(messageHeadersMock); expect(requestChannel.send(messageMock)).andReturn(true); - expect(messageHeadersMock.getId()).andReturn(1); + expect(messageHeadersMock.getId()).andReturn(UUID.randomUUID()); //play scenario replay(allmocks); @@ -194,7 +198,7 @@ public class SimpleMessagingGatewayTests { expect(messageMock.getHeaders()).andReturn(messageHeadersMock); expect(messageHeadersMock.getReplyChannel()).andReturn(replyChannel); expect(requestChannel.send(messageMock)).andReturn(true); - expect(messageHeadersMock.getId()).andReturn(1); + expect(messageHeadersMock.getId()).andReturn(UUID.randomUUID()); replay(allmocks); this.simpleMessagingGateway.sendAndReceiveMessage(messageMock); diff --git a/org.springframework.integration/src/test/java/org/springframework/integration/json/InboundJsonMessageMapperTests.java b/org.springframework.integration/src/test/java/org/springframework/integration/json/InboundJsonMessageMapperTests.java index 26bc3a3540..54b344b236 100644 --- a/org.springframework.integration/src/test/java/org/springframework/integration/json/InboundJsonMessageMapperTests.java +++ b/org.springframework.integration/src/test/java/org/springframework/integration/json/InboundJsonMessageMapperTests.java @@ -1,3 +1,19 @@ +/* + * 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. + */ + package org.springframework.integration.json; import static org.junit.Assert.assertEquals; @@ -9,6 +25,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.map.JsonMappingException; @@ -19,14 +36,19 @@ import org.springframework.integration.core.Message; import org.springframework.integration.core.MessageHeaders; import org.springframework.integration.message.MessageBuilder; +/** + * @author Jeremy Grelle + * @author Mark Fisher + */ public class InboundJsonMessageMapperTests { ObjectMapper mapper = new ObjectMapper(); @Test public void testToMessageWithHeadersAndStringPayload() throws Exception { - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"},\"payload\":\"myPayloadStuff\"}"; - Message expected = MessageBuilder.withPayload("myPayloadStuff").setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID,"myUniqueId").build(); + 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); Message result = mapper.toMessage(jsonMessage); assertEquals(expected, result); @@ -45,8 +67,9 @@ public class InboundJsonMessageMapperTests { @Test public void testToMessageWithHeadersAndBeanPayload() throws Exception { TestBean bean = new TestBean(); - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"},\"payload\":"+getBeanAsJson(bean)+"}"; - Message expected = MessageBuilder.withPayload(bean).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID,"myUniqueId").build(); + 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); Message result = mapper.toMessage(jsonMessage); assertEquals(expected, result); @@ -65,9 +88,10 @@ public class InboundJsonMessageMapperTests { @Test public void testToMessageWithBeanHeaderAndStringPayload() throws Exception { TestBean bean = new TestBean(); - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\", \"myHeader\":"+getBeanAsJson(bean)+"},\"payload\":\"myPayloadStuff\"}"; + UUID id = UUID.randomUUID(); + 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,"myUniqueId").setHeader("myHeader", bean).build(); + setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).setHeader("myHeader", bean).build(); InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); Map> headerTypes = new HashMap>(); headerTypes.put("myHeader", TestBean.class); @@ -78,9 +102,10 @@ public class InboundJsonMessageMapperTests { @Test public void testToMessageWithHeadersAndListOfStringsPayload() throws Exception { - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"},\"payload\":[\"myPayloadStuff1\",\"myPayloadStuff2\",\"myPayloadStuff3\"]}"; + UUID id = UUID.randomUUID(); + 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,"myUniqueId").build(); + Message> expected = MessageBuilder.withPayload(expectedList).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).build(); InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(new TypeReference>(){}); Message result = mapper.toMessage(jsonMessage); assertEquals(expected, result); @@ -90,9 +115,10 @@ public class InboundJsonMessageMapperTests { public void testToMessageWithHeadersAndListOfBeansPayload() throws Exception { TestBean bean1 = new TestBean(); TestBean bean2 = new TestBean(); - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"},\"payload\":["+getBeanAsJson(bean1)+","+getBeanAsJson(bean2)+"]}"; + UUID id = UUID.randomUUID(); + 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,"myUniqueId").build(); + Message> expected = MessageBuilder.withPayload(expectedList).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).build(); InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(new TypeReference>(){}); Message result = mapper.toMessage(jsonMessage); assertEquals(expected, result); @@ -100,87 +126,96 @@ public class InboundJsonMessageMapperTests { @Test public void testToMessageInvalidFormatPayloadAndHeadersReversed() throws Exception { - String jsonMessage = "{\"payload\":\"myPayloadStuff\",\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"}}"; + UUID id = UUID.randomUUID(); + String jsonMessage = "{\"payload\":\"myPayloadStuff\",\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"}}"; InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); - try { mapper.toMessage(jsonMessage); fail(); - } catch(IllegalArgumentException ex) { + } + catch(IllegalArgumentException ex) { //Expected } } - + @Test public void testToMessageInvalidFormatPayloadNoHeaders() throws Exception { String jsonMessage = "{\"payload\":\"myPayloadStuff\"}"; InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); - try { mapper.toMessage(jsonMessage); fail(); - } catch(IllegalArgumentException ex) { + } + catch(IllegalArgumentException ex) { //Expected } } - + @Test public void testToMessageInvalidFormatHeadersNoPayload() throws Exception { - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"}}"; + UUID id = UUID.randomUUID(); + String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"}}"; InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); - try { mapper.toMessage(jsonMessage); fail(); - } catch(IllegalArgumentException ex) { + } + catch(IllegalArgumentException ex) { //Expected } } - + @Test public void testToMessageInvalidFormatHeadersAndStringPayloadWithMapToPayload() throws Exception { - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"},\"payload\":\"myPayloadStuff\"}"; + UUID id = UUID.randomUUID(); + String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":\"myPayloadStuff\"}"; InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); mapper.setMapToPayload(true); try { mapper.toMessage(jsonMessage); fail(); - } catch(IllegalArgumentException ex) { + } + catch(IllegalArgumentException ex) { //Expected } } - + @Test public void testToMessageInvalidFormatHeadersAndBeanPayloadWithMapToPayload() throws Exception { TestBean bean = new TestBean(); - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"},\"payload\":"+getBeanAsJson(bean)+"}"; + UUID id = UUID.randomUUID(); + String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":" + getBeanAsJson(bean) + "}"; InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(TestBean.class); mapper.setMapToPayload(true); try { mapper.toMessage(jsonMessage); fail(); - } catch(IllegalArgumentException ex) { + } + catch(IllegalArgumentException ex) { //Expected } } - + @Test public void testToMessageWithHeadersAndPayloadTypeMappingFailure() throws Exception { TestBean bean = new TestBean(); - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\"},\"payload\":"+getBeanAsJson(bean)+"}"; + UUID id = UUID.randomUUID(); + String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\"},\"payload\":" + getBeanAsJson(bean) + "}"; InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(Long.class); try { mapper.toMessage(jsonMessage); fail(); - } catch(IllegalArgumentException ex) { + } + catch(IllegalArgumentException ex) { //Expected } } - + @Test public void testToMessageWithBeanHeaderTypeMappingFailure() throws Exception { TestBean bean = new TestBean(); - String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"myUniqueId\",\"myHeader\":"+getBeanAsJson(bean)+"},\"payload\":\"myPayloadStuff\"}"; + UUID id = UUID.randomUUID(); + String jsonMessage = "{\"headers\":{\"$timestamp\":1,\"$id\":\"" + id + "\",\"myHeader\":" + getBeanAsJson(bean) + "},\"payload\":\"myPayloadStuff\"}"; InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(String.class); Map> headerTypes = new HashMap>(); headerTypes.put("myHeader", Long.class); @@ -188,16 +223,17 @@ public class InboundJsonMessageMapperTests { try { mapper.toMessage(jsonMessage); fail(); - } catch(IllegalArgumentException ex) { + } + catch(IllegalArgumentException ex) { //Expected } } - - - + + private String getBeanAsJson(TestBean bean) throws JsonGenerationException, JsonMappingException, IOException { StringWriter writer = new StringWriter(); mapper.writeValue(writer, bean); return writer.toString(); } + }