INT-1053 Message ID is now always a UUID rather than any Object type

This commit is contained in:
Mark Fisher
2010-03-29 17:20:28 +00:00
parent e4dc5e41e7
commit bde0bca24e
5 changed files with 129 additions and 71 deletions

View File

@@ -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<String, Object>, 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 <b>except</b> 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<String, Object>, Serializable {
}
public Object getId() {
return this.get(ID);
public UUID getId() {
return this.get(ID, UUID.class);
}
public Long getTimestamp() {

View File

@@ -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<String, Class<?>>();
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);
}

View File

@@ -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<Object>() {
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<Message<?>> storedMessages = new ArrayList<Message<?>>();
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.<Message<?>>asList(message1))).thenReturn(false);
handler.handleMessage(message1);
storedMessages.add(message1);
when(completionStrategy.isComplete(Arrays.asList(message1, message2))).thenReturn(true);
when(completionStrategy.isComplete(Arrays.<Message<?>>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.<Message<?>>asList(message1));
verify(completionStrategy).isComplete(Arrays.<Message<?>>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<Message<?>> storedMessages = new ArrayList<Message<?>>();
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<Boolean>() {
public Boolean answer(InvocationOnMock invocation) throws Throwable {
Thread.sleep(50);
return true;
}
}).thenReturn(true);
when(completionStrategy.isComplete(Arrays.<Message<?>>asList(message1, message2)))
.thenAnswer(new Answer<Boolean>() {
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)

View File

@@ -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);

View File

@@ -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<String> 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<String> 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<TestBean> 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<TestBean> 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<String> 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<String, Class<?>> headerTypes = new HashMap<String, Class<?>>();
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<String> expectedList = Arrays.asList(new String[]{"myPayloadStuff1", "myPayloadStuff2", "myPayloadStuff3"});
Message<List<String>> expected = MessageBuilder.withPayload(expectedList).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID,"myUniqueId").build();
Message<List<String>> expected = MessageBuilder.withPayload(expectedList).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).build();
InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(new TypeReference<List<String>>(){});
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<TestBean> expectedList = Arrays.asList(new TestBean[]{bean1, bean2});
Message<List<TestBean>> expected = MessageBuilder.withPayload(expectedList).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID,"myUniqueId").build();
Message<List<TestBean>> expected = MessageBuilder.withPayload(expectedList).setHeader(MessageHeaders.TIMESTAMP, new Long(1)).setHeader(MessageHeaders.ID, id).build();
InboundJsonMessageMapper mapper = new InboundJsonMessageMapper(new TypeReference<List<TestBean>>(){});
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<String, Class<?>> headerTypes = new HashMap<String, Class<?>>();
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();
}
}