@Override protected void handleMessageInternal(Message<?> message) throws Exception { Object correlationKey = this.correlationStrategy.getCorrelationKey(message); Object lock = getLock(correlationKey); synchronized (lock) { this.store.addMessagesToGroup(correlationKey, message); } if (log.isDebugEnabled()) { log.debug(String.format("Handled message for key [%s]: %s.", correlationKey, message)); } }
@Test @MongoDbAvailable public void testNonExistingEmptyMessageGroup() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = getMessageGroupStore(); store.addMessagesToGroup(1, new GenericMessage<Object>("foo")); MessageGroup messageGroup = store.getMessageGroup(1); assertNotNull(messageGroup); assertThat(messageGroup.getClass().getName(), containsString("PersistentMessageGroup")); assertEquals(1, messageGroup.size()); }
@Test @MongoDbAvailable public void testMessageGroupIterator() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store1 = this.getMessageGroupStore(); MessageGroupStore store2 = this.getMessageGroupStore(); Message<?> message = new GenericMessage<String>("1"); store2.addMessagesToGroup("1", message); store1.addMessagesToGroup("2", new GenericMessage<String>("2")); store2.addMessagesToGroup("3", new GenericMessage<String>("3")); MessageGroupStore store3 = this.getMessageGroupStore(); Iterator<MessageGroup> iterator = store3.iterator(); assertNotNull(iterator); int counter = 0; while (iterator.hasNext()) { iterator.next(); counter++; } assertEquals(3, counter); store2.removeMessagesFromGroup("1", message); iterator = store3.iterator(); counter = 0; while (iterator.hasNext()) { iterator.next(); counter++; } assertEquals(2, counter); }
@Test @MongoDbAvailable public void testCountMessagesInGroup() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); Message<?> messageA = new GenericMessage<String>("A"); Message<?> messageB = new GenericMessage<String>("B"); store.addMessagesToGroup(1, messageA, messageB); assertEquals(2, store.messageGroupSize(1)); }
@Test @MongoDbAvailable public void testPollMessages() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); Message<?> messageA = new GenericMessage<String>("A"); Message<?> messageB = new GenericMessage<String>("B"); store.addMessagesToGroup(1, messageA); Thread.sleep(10); store.addMessagesToGroup(1, messageB); assertEquals(2, store.messageGroupSize(1)); Message<?> out = store.pollMessageFromGroup(1); assertNotNull(out); assertEquals("A", out.getPayload()); assertEquals(1, store.messageGroupSize(1)); out = store.pollMessageFromGroup(1); assertEquals("B", out.getPayload()); assertEquals(0, store.messageGroupSize(1)); }
@Test /* INT-3216 */ public void testDontReapIfAlreadyComplete() throws Exception { MessageGroupProcessor mgp = new DefaultAggregatingMessageGroupProcessor(); AggregatingMessageHandler handler = new AggregatingMessageHandler(mgp); handler.setReleaseStrategy(group -> true); QueueChannel outputChannel = new QueueChannel(); handler.setOutputChannel(outputChannel); MessageGroupStore mgs = TestUtils.getPropertyValue(handler, "messageStore", MessageGroupStore.class); mgs.addMessagesToGroup("foo", new GenericMessage<>("foo")); mgs.completeGroup("foo"); mgs = spy(mgs); new DirectFieldAccessor(handler).setPropertyValue("messageStore", mgs); Method forceComplete = AbstractCorrelatingMessageHandler.class.getDeclaredMethod("forceComplete", MessageGroup.class); forceComplete.setAccessible(true); MessageGroup group = (MessageGroup) TestUtils.getPropertyValue(mgs, "groupIdToMessageGroup", Map.class) .get("foo"); assertTrue(group.isComplete()); forceComplete.invoke(handler, group); verify(mgs, never()).getMessageGroup("foo"); assertNull(outputChannel.receive(0)); }
@Test @MongoDbAvailable public void testMessageGroupWithAddedMessagePrimitiveGroupId() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); MessageStore messageStore = this.getMessageStore(); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> messageA = new GenericMessage<String>("A"); Message<?> messageB = new GenericMessage<String>("B"); store.addMessagesToGroup(1, messageA); messageGroup = store.addMessageToGroup(1, messageB); assertNotNull(messageGroup); assertEquals(2, messageGroup.size()); Message<?> retrievedMessage = messageStore.getMessage(messageA.getHeaders().getId()); assertNotNull(retrievedMessage); assertEquals(retrievedMessage.getHeaders().getId(), messageA.getHeaders().getId()); // ensure that 'message_group' header that is only used internally is not propagated assertNull(retrievedMessage.getHeaders().get("message_group")); }
@Test @MongoDbAvailable public void testCompleteMessageGroup() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); MessageGroup messageGroup = store.getMessageGroup(1); assertNotNull(messageGroup); Message<?> message = new GenericMessage<String>("Hello"); store.addMessagesToGroup(messageGroup.getGroupId(), message); store.completeGroup(messageGroup.getGroupId()); messageGroup = store.getMessageGroup(1); assertTrue(messageGroup.isComplete()); }
@Test public void testReapWithChangeInSameMillisecond() throws Exception { MessageGroupProcessor mgp = new DefaultAggregatingMessageGroupProcessor(); AggregatingMessageHandler handler = new AggregatingMessageHandler(mgp); handler.setReleaseStrategy(group -> true); QueueChannel outputChannel = new QueueChannel(); handler.setOutputChannel(outputChannel); MessageGroupStore mgs = TestUtils.getPropertyValue(handler, "messageStore", MessageGroupStore.class); Method forceComplete = AbstractCorrelatingMessageHandler.class.getDeclaredMethod("forceComplete", MessageGroup.class); forceComplete.setAccessible(true); GenericMessage<String> secondMessage = new GenericMessage<>("bar"); mgs.addMessagesToGroup("foo", new GenericMessage<>("foo"), secondMessage); MessageGroup group = mgs.getMessageGroup("foo"); // remove a message mgs.removeMessagesFromGroup("foo", secondMessage); // force lastModified to be the same MessageGroup groupNow = mgs.getMessageGroup("foo"); new DirectFieldAccessor(group).setPropertyValue("lastModified", groupNow.getLastModified()); forceComplete.invoke(handler, group); Message<?> message = outputChannel.receive(0); assertNotNull(message); Collection<?> payload = (Collection<?>) message.getPayload(); assertEquals(1, payload.size()); }
@Test @MongoDbAvailable public void testMessageGroupWithAddedMessageUUIDGroupIdAndUUIDHeader() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); MessageStore messageStore = this.getMessageStore(); Object id = UUID.randomUUID(); MessageGroup messageGroup = store.getMessageGroup(id); UUID uuidA = UUID.randomUUID(); Message<?> messageA = MessageBuilder.withPayload("A").setHeader("foo", uuidA).build(); UUID uuidB = UUID.randomUUID(); Message<?> messageB = MessageBuilder.withPayload("B").setHeader("foo", uuidB).build(); store.addMessagesToGroup(id, messageA); messageGroup = store.addMessageToGroup(id, messageB); assertNotNull(messageGroup); assertEquals(2, messageGroup.size()); Message<?> retrievedMessage = messageStore.getMessage(messageA.getHeaders().getId()); assertNotNull(retrievedMessage); assertEquals(retrievedMessage.getHeaders().getId(), messageA.getHeaders().getId()); // ensure that 'message_group' header that is only used internally is not propagated assertNull(retrievedMessage.getHeaders().get("message_group")); Object fooHeader = retrievedMessage.getHeaders().get("foo"); assertTrue(fooHeader instanceof UUID); assertEquals(uuidA, fooHeader); }
@Test @MongoDbAvailable public void testLastReleasedSequenceNumber() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); MessageGroup messageGroup = store.getMessageGroup(1); assertNotNull(messageGroup); Message<?> message = new GenericMessage<String>("Hello"); store.addMessagesToGroup(messageGroup.getGroupId(), message); store.setLastReleasedSequenceNumberForGroup(messageGroup.getGroupId(), 5); messageGroup = store.getMessageGroup(1); assertEquals(5, messageGroup.getLastReleasedMessageSequenceNumber()); }
@Test @MongoDbAvailable public void testWithMessageHistory() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); store.getMessageGroup(1); Message<?> message = new GenericMessage<String>("Hello"); DirectChannel fooChannel = new DirectChannel(); fooChannel.setBeanName("fooChannel"); DirectChannel barChannel = new DirectChannel(); barChannel.setBeanName("barChannel"); message = MessageHistory.write(message, fooChannel); message = MessageHistory.write(message, barChannel); store.addMessagesToGroup(1, message); MessageGroup group = store.getMessageGroup(1); assertNotNull(group); Collection<Message<?>> messages = group.getMessages(); assertTrue(!messages.isEmpty()); message = messages.iterator().next(); MessageHistory messageHistory = MessageHistory.read(message); assertNotNull(messageHistory); assertEquals(2, messageHistory.size()); Properties fooChannelHistory = messageHistory.get(0); assertEquals("fooChannel", fooChannelHistory.get("name")); assertEquals("channel", fooChannelHistory.get("type")); }
@Test public void testDontReapIfAlreadyCompleteAfterRefetch() throws Exception { MessageGroupProcessor mgp = new DefaultAggregatingMessageGroupProcessor(); AggregatingMessageHandler handler = new AggregatingMessageHandler(mgp); handler.setReleaseStrategy(group -> true); QueueChannel outputChannel = new QueueChannel(); handler.setOutputChannel(outputChannel); MessageGroupStore mgs = TestUtils.getPropertyValue(handler, "messageStore", MessageGroupStore.class); mgs.addMessagesToGroup("foo", new GenericMessage<>("foo")); MessageGroup group = new SimpleMessageGroup(mgs.getMessageGroup("foo")); mgs.completeGroup("foo"); mgs = spy(mgs); new DirectFieldAccessor(handler).setPropertyValue("messageStore", mgs); Method forceComplete = AbstractCorrelatingMessageHandler.class.getDeclaredMethod("forceComplete", MessageGroup.class); forceComplete.setAccessible(true); MessageGroup groupInStore = (MessageGroup) TestUtils.getPropertyValue(mgs, "groupIdToMessageGroup", Map.class) .get("foo"); assertTrue(groupInStore.isComplete()); assertFalse(group.isComplete()); new DirectFieldAccessor(group).setPropertyValue("lastModified", groupInStore.getLastModified()); forceComplete.invoke(handler, group); verify(mgs).getMessageGroup("foo"); assertNull(outputChannel.receive(0)); }
@Test public void testDontReapIfNewGroupFoundDuringRefetch() throws Exception { MessageGroupProcessor mgp = new DefaultAggregatingMessageGroupProcessor(); AggregatingMessageHandler handler = new AggregatingMessageHandler(mgp); handler.setReleaseStrategy(group -> true); QueueChannel outputChannel = new QueueChannel(); handler.setOutputChannel(outputChannel); MessageGroupStore mgs = TestUtils.getPropertyValue(handler, "messageStore", MessageGroupStore.class); mgs.addMessagesToGroup("foo", new GenericMessage<>("foo")); MessageGroup group = new SimpleMessageGroup(mgs.getMessageGroup("foo")); mgs = spy(mgs); new DirectFieldAccessor(handler).setPropertyValue("messageStore", mgs); Method forceComplete = AbstractCorrelatingMessageHandler.class.getDeclaredMethod("forceComplete", MessageGroup.class); forceComplete.setAccessible(true); MessageGroup groupInStore = (MessageGroup) TestUtils.getPropertyValue(mgs, "groupIdToMessageGroup", Map.class) .get("foo"); assertFalse(groupInStore.isComplete()); assertFalse(group.isComplete()); DirectFieldAccessor directFieldAccessor = new DirectFieldAccessor(group); directFieldAccessor.setPropertyValue("lastModified", groupInStore.getLastModified()); directFieldAccessor.setPropertyValue("timestamp", groupInStore.getTimestamp() - 1); forceComplete.invoke(handler, group); verify(mgs).getMessageGroup("foo"); assertNull(outputChannel.receive(0)); }
@Test @MongoDbAvailable public void testAddAndRemoveMessagesFromMessageGroup() throws Exception { MessageGroupStore messageStore = (MessageGroupStore) this.getMessageStore(); String groupId = "X"; messageStore.removeMessageGroup("X"); ((AbstractBatchingMessageGroupStore) messageStore).setRemoveBatchSize(10); List<Message<?>> messages = new ArrayList<Message<?>>(); for (int i = 0; i < 25; i++) { Message<String> message = MessageBuilder.withPayload("foo").setCorrelationId(groupId).build(); messageStore.addMessagesToGroup(groupId, message); messages.add(message); } MessageGroup group = messageStore.getMessageGroup(groupId); assertEquals(25, group.size()); messageStore.removeMessagesFromGroup(groupId, messages); group = messageStore.getMessageGroup(groupId); assertEquals(0, group.size()); }
@Test @MongoDbAvailable public void testRemoveMessageFromTheGroup() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> message = new GenericMessage<String>("2"); store.addMessagesToGroup(1, new GenericMessage<String>("1"), message); messageGroup = store.addMessageToGroup(1, new GenericMessage<String>("3")); assertNotNull(messageGroup); assertEquals(3, messageGroup.size()); store.removeMessagesFromGroup(1, message); messageGroup = store.getMessageGroup(1); assertEquals(2, messageGroup.size()); }
@Test @MongoDbAvailable public void testMultipleMessageStores() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store1 = this.getMessageGroupStore(); MessageGroupStore store2 = this.getMessageGroupStore(); Message<?> message = new GenericMessage<String>("1"); store1.addMessagesToGroup(1, message, new GenericMessage<String>("2"), new GenericMessage<String>("3")); MessageGroupStore store3 = this.getMessageGroupStore(); MessageGroup messageGroup = store3.getMessageGroup(1); assertNotNull(messageGroup); assertEquals(3, messageGroup.size()); store3.removeMessagesFromGroup(1, message); messageGroup = store2.getMessageGroup(1); assertEquals(2, messageGroup.size()); }
@Test @MongoDbAvailable public void testMessageGroupMarkingMessage() throws Exception { this.cleanupCollections(new SimpleMongoDbFactory(new MongoClient(), "test")); MessageGroupStore store = this.getMessageGroupStore(); MessageGroup messageGroup = store.getMessageGroup(1); Message<?> messageA = new GenericMessage<String>("A"); Message<?> messageB = new GenericMessage<String>("B"); store.addMessagesToGroup(1, messageA); messageGroup = store.addMessageToGroup(1, messageB); assertNotNull(messageGroup); assertEquals(2, messageGroup.size()); store.removeMessagesFromGroup(1, messageA); messageGroup = store.getMessageGroup(1); assertEquals(1, messageGroup.size()); // validate that the updates were propagated to Mongo as well store = this.getMessageGroupStore(); messageGroup = store.getMessageGroup(1); assertEquals(1, messageGroup.size()); }
store.addMessagesToGroup(1, messageA); store.addMessagesToGroup(2, messageA); store.addMessagesToGroup(3, messageA); store.addMessagesToGroup(4, messageA); assertEquals(1, store.messageGroupSize(1)); assertEquals(1, store.messageGroupSize(2));
MessageGroupStore store = this.getMessageGroupStore(); Message<?> messageA = new GenericMessage<String>("A"); store.addMessagesToGroup(1, messageA); store.addMessagesToGroup(2, messageA); store.addMessagesToGroup(3, messageA); store.addMessagesToGroup(4, messageA); assertEquals(1, store.messageGroupSize(1)); assertEquals(1, store.messageGroupSize(2));