@Test public void completesAfterSequenceComplete() throws Exception { Message<?> message1 = correlatedMessage(1, 2, 1); Message<?> message2 = correlatedMessage(1, 2, 2); defaultHandler.handleMessage(message1); verify(outputChannel, never()).send(message1); defaultHandler.handleMessage(message2); verify(outputChannel).send(message1); verify(outputChannel).send(message2); }
@Test public void completesSingleMessage() throws Exception { Message<?> message = correlatedMessage(1, 1, 1); defaultHandler.handleMessage(message); verify(outputChannel).send(message); }
@Test public void completesWithoutReleasingIncompleteCorrelations() throws Exception { Message<?> message1 = correlatedMessage(1, 2, 1); Message<?> message2 = correlatedMessage(2, 2, 1); Message<?> message1a = correlatedMessage(1, 2, 2); Message<?> message2a = correlatedMessage(2, 2, 2); defaultHandler.handleMessage(message1); defaultHandler.handleMessage(message2); verify(outputChannel, never()).send(message1); verify(outputChannel, never()).send(message2); defaultHandler.handleMessage(message1a); verify(outputChannel).send(message1); verify(outputChannel).send(message1a); verify(outputChannel, never()).send(message2); verify(outputChannel, never()).send(message2a); defaultHandler.handleMessage(message2a); verify(outputChannel).send(message2); verify(outputChannel).send(message2a); }
@Test public void completesAfterThreshold() throws Exception { defaultHandler.setReleaseStrategy(new MessageCountReleaseStrategy()); MessageChannel discardChannel = mock(MessageChannel.class); when(discardChannel.send(any(Message.class))).thenReturn(true); defaultHandler.setDiscardChannel(discardChannel); Message<?> message1 = correlatedMessage(1, 2, 1); Message<?> message2 = correlatedMessage(1, 2, 2); defaultHandler.handleMessage(message1); verify(outputChannel).send(message1); defaultHandler.handleMessage(message2); verify(outputChannel, never()).send(message2); verify(discardChannel).send(message2); }
@Test public void testAdditionalMessageAfterCompletion() { QueueChannel replyChannel = new QueueChannel(); Message<?> message1 = createMessage(3, "ABC", 3, 1, replyChannel, null); Message<?> message2 = createMessage(5, "ABC", 3, 2, replyChannel, null); Message<?> message3 = createMessage(7, "ABC", 3, 3, replyChannel, null); Message<?> message4 = createMessage(7, "ABC", 3, 3, replyChannel, null); this.aggregator.handleMessage(message1); this.aggregator.handleMessage(message2); this.aggregator.handleMessage(message3); this.aggregator.handleMessage(message4); Message<?> reply = replyChannel.receive(10000); assertNotNull("A message should be aggregated", reply); assertThat((reply.getPayload()), is(105)); }
@Test public void completesIfNoSequence() throws Exception { defaultHandler.setReleaseStrategy(new MessageCountReleaseStrategy(2)); Message<?> message1 = MessageBuilder.withPayload(1).setCorrelationId("foo").build(); Message<?> message2 = MessageBuilder.withPayload(2).setCorrelationId("foo").build(); Message<?> message3 = MessageBuilder.withPayload(3).setCorrelationId("foo").build(); defaultHandler.handleMessage(message1); verify(outputChannel, never()).send(message3); defaultHandler.handleMessage(message2); verify(outputChannel).send(message2); defaultHandler.handleMessage(message3); verify(outputChannel, never()).send(message3); }
@Test public void bufferCompletesNormally() throws Exception { String correlationKey = "key"; Message<?> message1 = testMessage(correlationKey, 1, 2); Message<?> message2 = testMessage(correlationKey, 2, 2); when(correlationStrategy.getCorrelationKey(isA(Message.class))).thenReturn(correlationKey); when(processor.processMessageGroup(any(MessageGroup.class))).thenReturn(MessageBuilder.withPayload("grouped").build()); when(outputChannel.send(any(Message.class))).thenReturn(true); handler.handleMessage(message1); handler.handleMessage(message2); verify(correlationStrategy).getCorrelationKey(message1); verify(correlationStrategy).getCorrelationKey(message2); verify(processor).processMessageGroup(isA(SimpleMessageGroup.class)); }
@Test public void shouldRejectDuplicatedSequenceNumbers() { QueueChannel replyChannel = new QueueChannel(); Message<?> message1 = createMessage(3, "ABC", 3, 1, replyChannel, null); Message<?> message2 = createMessage(5, "ABC", 3, 2, replyChannel, null); Message<?> message3 = createMessage(7, "ABC", 3, 3, replyChannel, null); Message<?> message4 = createMessage(7, "ABC", 3, 3, replyChannel, null); this.aggregator.setReleaseStrategy(new SequenceSizeReleaseStrategy()); this.aggregator.handleMessage(message1); this.aggregator.handleMessage(message3); // duplicated sequence number, either message3 or message4 should be rejected this.aggregator.handleMessage(message4); this.aggregator.handleMessage(message2); Message<?> reply = replyChannel.receive(10000); assertNotNull("A message should be aggregated", reply); assertThat((reply.getPayload()), is(105)); }
@Test(expected = MessageHandlingException.class) public void testExceptionThrownIfNoCorrelationId() { Message<?> message = createMessage(3, null, 2, 1, new QueueChannel(), null); this.aggregator.handleMessage(message); }
@Test(expected = MessageHandlingException.class) public void testExceptionThrownIfNoCorrelationId() throws InterruptedException { Message<?> message = createMessage(3, null, 2, 1, new QueueChannel(), null); this.aggregator.handleMessage(message); }
@Test public void testNullCorrelationKey() throws Exception { final Message<?> message1 = MessageBuilder.withPayload("foo").build(); when(correlationStrategy.getCorrelationKey(isA(Message.class))).thenReturn(null); try { handler.handleMessage(message1); fail("Expected MessageHandlingException"); } catch (MessageHandlingException e) { Throwable cause = e.getCause(); boolean pass = cause instanceof IllegalStateException && cause.getMessage().toLowerCase().contains("null correlation"); if (!pass) { throw e; } } }
@Test public void testCompleteGroupWithinTimeout() { QueueChannel replyChannel = new QueueChannel(); MessageChannel lockCheckingChannel = (m, to) -> { checkLock(this.aggregator, "ABC", true); replyChannel.send(m); return true; }; Message<?> message1 = createMessage(3, "ABC", 3, 1, lockCheckingChannel, null); Message<?> message2 = createMessage(5, "ABC", 3, 2, lockCheckingChannel, null); Message<?> message3 = createMessage(7, "ABC", 3, 3, lockCheckingChannel, null); this.aggregator.handleMessage(message1); this.aggregator.handleMessage(message2); this.aggregator.handleMessage(message3); Message<?> reply = replyChannel.receive(10000); assertNotNull(reply); assertEquals(reply.getPayload(), 105); }
@Test @Ignore // dropped backwards compatibility for setting capacity limit (it's always Integer.MAX_VALUE) public void testTrackedCorrelationIdsCapacityAtLimit() { QueueChannel replyChannel = new QueueChannel(); QueueChannel discardChannel = new QueueChannel(); this.aggregator.setDiscardChannel(discardChannel); this.aggregator.handleMessage(createMessage(1, 1, 1, 1, replyChannel, null)); assertEquals(1, replyChannel.receive(1000).getPayload()); this.aggregator.handleMessage(createMessage(3, 2, 1, 1, replyChannel, null)); assertEquals(3, replyChannel.receive(1000).getPayload()); this.aggregator.handleMessage(createMessage(4, 3, 1, 1, replyChannel, null)); assertEquals(4, replyChannel.receive(1000).getPayload()); // next message with same correllation ID is discarded this.aggregator.handleMessage(createMessage(2, 1, 1, 1, replyChannel, null)); assertEquals(2, discardChannel.receive(1000).getPayload()); }
@Test @Ignore // dropped backwards compatibility for setting capacity limit (it's always Integer.MAX_VALUE) public void testTrackedCorrelationIdsCapacityPassesLimit() { QueueChannel replyChannel = new QueueChannel(); QueueChannel discardChannel = new QueueChannel(); this.aggregator.setDiscardChannel(discardChannel); this.aggregator.handleMessage(createMessage(1, 1, 1, 1, replyChannel, null)); assertEquals(1, replyChannel.receive(1000).getPayload()); this.aggregator.handleMessage(createMessage(2, 2, 1, 1, replyChannel, null)); assertEquals(2, replyChannel.receive(1000).getPayload()); this.aggregator.handleMessage(createMessage(3, 3, 1, 1, replyChannel, null)); assertEquals(3, replyChannel.receive(1000).getPayload()); this.aggregator.handleMessage(createMessage(4, 4, 1, 1, replyChannel, null)); assertEquals(4, replyChannel.receive(1000).getPayload()); this.aggregator.handleMessage(createMessage(5, 1, 1, 1, replyChannel, null)); assertEquals(5, replyChannel.receive(1000).getPayload()); assertNull(discardChannel.receive(0)); }
@Test public void testCompleteGroupWithinTimeoutUnlockB4Send() { QueueChannel replyChannel = new QueueChannel(); MessageChannel lockCheckingChannel = (m, to) -> { checkLock(this.aggregator, "ABC", false); replyChannel.send(m); return true; }; Message<?> message1 = createMessage(3, "ABC", 3, 1, lockCheckingChannel, null); Message<?> message2 = createMessage(5, "ABC", 3, 2, lockCheckingChannel, null); Message<?> message3 = createMessage(7, "ABC", 3, 3, lockCheckingChannel, null); this.aggregator.setReleaseLockBeforeSend(true); this.aggregator.handleMessage(message1); this.aggregator.handleMessage(message2); this.aggregator.handleMessage(message3); Message<?> reply = replyChannel.receive(10000); assertNotNull(reply); assertEquals(reply.getPayload(), 105); }
@Test public void batchingWithoutLeftovers() { QueueChannel outputChannel = new QueueChannel(); QueueChannel discardChannel = new QueueChannel(); defaultHandler.setOutputChannel(outputChannel); defaultHandler.setDiscardChannel(discardChannel); defaultHandler.setReleaseStrategy(new SampleSizeReleaseStrategy()); defaultHandler.setExpireGroupsUponCompletion(true); for (int i = 0; i < 10; i++) { defaultHandler.handleMessage(MessageBuilder.withPayload(i).setCorrelationId("A").build()); } assertEquals(5, ((List<?>) outputChannel.receive(0).getPayload()).size()); assertEquals(5, ((List<?>) outputChannel.receive(0).getPayload()).size()); assertNull(discardChannel.receive(0)); }
@Test public void batchingWithLeftovers() { QueueChannel outputChannel = new QueueChannel(); QueueChannel discardChannel = new QueueChannel(); defaultHandler.setOutputChannel(outputChannel); defaultHandler.setDiscardChannel(discardChannel); defaultHandler.setReleaseStrategy(new SampleSizeReleaseStrategy()); defaultHandler.setExpireGroupsUponCompletion(true); for (int i = 0; i < 12; i++) { defaultHandler.handleMessage(MessageBuilder.withPayload(i).setCorrelationId("A").build()); } assertEquals(5, ((List<?>) outputChannel.receive(0).getPayload()).size()); assertEquals(5, ((List<?>) outputChannel.receive(0).getPayload()).size()); assertNull(discardChannel.receive(0)); assertEquals(2, store.getMessageGroup("A").getMessages().size()); }
@Test public void waitForAllCustomReleaseStrategyWithLateArrivals() { QueueChannel outputChannel = new QueueChannel(); QueueChannel discardChannel = new QueueChannel(); defaultHandler.setOutputChannel(outputChannel); defaultHandler.setDiscardChannel(discardChannel); defaultHandler.setReleaseStrategy(new SampleSizeReleaseStrategy()); for (int i = 0; i < 5; i++) { defaultHandler.handleMessage(MessageBuilder.withPayload(i).setCorrelationId("A").build()); } assertEquals(5, ((List<?>) outputChannel.receive(0).getPayload()).size()); assertNull(discardChannel.receive(0)); assertEquals(0, store.getMessageGroup("A").getMessages().size()); // send another message with the same correlation id and see it in the discard channel defaultHandler.handleMessage(MessageBuilder.withPayload("foo").setCorrelationId("A").build()); assertNotNull(discardChannel.receive(0)); // expireMessageGroups from aggregator MessageStore and the messages should start accumulating again store.expireMessageGroups(0); defaultHandler.handleMessage(MessageBuilder.withPayload("foo").setCorrelationId("A").build()); assertNull(discardChannel.receive(0)); assertEquals(1, store.getMessageGroup("A").getMessages().size()); }
@Test @Ignore("Until 5.2 with new 'owner' feature on groups") public void testDontReapMessageOfOtherHandler() { MessageGroupStore groupStore = new SimpleMessageStore(); AggregatingMessageHandler handler1 = new AggregatingMessageHandler(group -> group, groupStore); AggregatingMessageHandler handler2 = new AggregatingMessageHandler(group -> group, groupStore); QueueChannel handler1DiscardChannel = new QueueChannel(); handler1.setDiscardChannel(handler1DiscardChannel); QueueChannel handler2DiscardChannel = new QueueChannel(); handler2.setDiscardChannel(handler2DiscardChannel); handler1.setReleaseStrategy(group -> false); handler2.setReleaseStrategy(group -> false); handler1.handleMessage(MessageBuilder.withPayload("foo").setCorrelationId("foo").build()); handler1.handleMessage(MessageBuilder.withPayload("foo").setCorrelationId("foo").build()); handler2.handleMessage(MessageBuilder.withPayload("foo").setCorrelationId("bar").build()); groupStore.expireMessageGroups(0); assertEquals(2, handler1DiscardChannel.getQueueSize()); assertEquals(1, handler2DiscardChannel.getQueueSize()); }
@Test public void firstBest() { QueueChannel outputChannel = new QueueChannel(); QueueChannel discardChannel = new QueueChannel(); defaultHandler.setOutputChannel(outputChannel); defaultHandler.setDiscardChannel(discardChannel); defaultHandler.setReleaseStrategy(new FirstBestReleaseStrategy()); for (int i = 0; i < 5; i++) { defaultHandler.handleMessage(MessageBuilder.withPayload(i).setCorrelationId("A").build()); } assertEquals(1, ((List<?>) outputChannel.receive(0).getPayload()).size()); assertNotNull(discardChannel.receive(0)); assertNotNull(discardChannel.receive(0)); assertNotNull(discardChannel.receive(0)); assertNotNull(discardChannel.receive(0)); }