Search in sources :

Example 6 with MessageGroup

use of org.springframework.integration.store.MessageGroup in project spring-integration by spring-projects.

the class AggregatingMessageGroupProcessorHeaderTests method testNullHeaderValue.

@Test
public void testNullHeaderValue() {
    DefaultAggregatingMessageGroupProcessor processor = new DefaultAggregatingMessageGroupProcessor();
    DirectFieldAccessor dfa = new DirectFieldAccessor(processor);
    dfa.setPropertyValue("messageBuilderFactory", new MutableMessageBuilderFactory());
    Map<String, Object> headers1 = new HashMap<String, Object>();
    headers1.put("k1", "foo");
    headers1.put("k2", null);
    Message<?> message1 = MutableMessageBuilder.withPayload("test").setCorrelationId(1).setSequenceNumber(1).setSequenceSize(2).copyHeadersIfAbsent(headers1).build();
    Map<String, Object> headers2 = new HashMap<String, Object>();
    headers2.put("k1", "bar");
    headers2.put("k2", 123);
    Message<?> message2 = correlatedMessage(1, 2, 2, headers2);
    List<Message<?>> messages = Arrays.<Message<?>>asList(message1, message2);
    MessageGroup group = new SimpleMessageGroup(messages, 1);
    Object result = processor.processMessageGroup(group);
    assertNotNull(result);
    assertTrue(result instanceof Message<?>);
    Message<?> resultMessage = (Message<?>) result;
    assertNull(resultMessage.getHeaders().get("k1"));
    assertNull(resultMessage.getHeaders().get("k2"));
    headers1 = new HashMap<String, Object>();
    headers1.put("k1", "foo");
    headers1.put("k2", 123);
    message1 = correlatedMessage(1, 2, 1, headers1);
    headers2 = new HashMap<String, Object>();
    headers2.put("k1", "bar");
    headers2.put("k2", null);
    message2 = MutableMessageBuilder.withPayload("test").setCorrelationId(1).setSequenceNumber(2).setSequenceSize(2).copyHeadersIfAbsent(headers2).build();
    messages = Arrays.<Message<?>>asList(message1, message2);
    group = new SimpleMessageGroup(messages, 1);
    result = processor.processMessageGroup(group);
    resultMessage = (Message<?>) result;
    assertNull(resultMessage.getHeaders().get("k1"));
    assertNull(resultMessage.getHeaders().get("k2"));
}
Also used : Message(org.springframework.messaging.Message) HashMap(java.util.HashMap) MessageGroup(org.springframework.integration.store.MessageGroup) SimpleMessageGroup(org.springframework.integration.store.SimpleMessageGroup) SimpleMessageGroup(org.springframework.integration.store.SimpleMessageGroup) DirectFieldAccessor(org.springframework.beans.DirectFieldAccessor) MutableMessageBuilderFactory(org.springframework.integration.support.MutableMessageBuilderFactory) Test(org.junit.Test)

Example 7 with MessageGroup

use of org.springframework.integration.store.MessageGroup in project spring-integration by spring-projects.

the class DelayHandlerTests method testReschedulePersistedMessagesOnStartup.

// INT-1132
@Test
public void testReschedulePersistedMessagesOnStartup() throws Exception {
    MessageGroupStore messageGroupStore = new SimpleMessageStore();
    this.delayHandler.setDefaultDelay(2000);
    this.delayHandler.setMessageStore(messageGroupStore);
    this.startDelayerHandler();
    Message<?> message = MessageBuilder.withPayload("test").build();
    this.input.send(message);
    Thread.sleep(100);
    // emulate restart
    this.taskScheduler.destroy();
    assertEquals(1, messageGroupStore.getMessageGroupCount());
    assertEquals(DELAYER_MESSAGE_GROUP_ID, messageGroupStore.iterator().next().getGroupId());
    assertEquals(1, messageGroupStore.messageGroupSize(DELAYER_MESSAGE_GROUP_ID));
    assertEquals(1, messageGroupStore.getMessageCountForAllMessageGroups());
    MessageGroup messageGroup = messageGroupStore.getMessageGroup(DELAYER_MESSAGE_GROUP_ID);
    Message<?> messageInStore = messageGroup.getMessages().iterator().next();
    Object payload = messageInStore.getPayload();
    assertEquals("DelayedMessageWrapper", payload.getClass().getSimpleName());
    assertEquals(message.getPayload(), TestUtils.getPropertyValue(payload, "original.payload"));
    this.taskScheduler.afterPropertiesSet();
    this.delayHandler = new DelayHandler(DELAYER_MESSAGE_GROUP_ID, this.taskScheduler);
    this.delayHandler.setOutputChannel(output);
    this.delayHandler.setDefaultDelay(200);
    this.delayHandler.setMessageStore(messageGroupStore);
    this.delayHandler.setBeanFactory(mock(BeanFactory.class));
    this.startDelayerHandler();
    waitForLatch(10000);
    assertSame(message.getPayload(), this.resultHandler.lastMessage.getPayload());
    assertNotSame(Thread.currentThread(), this.resultHandler.lastThread);
    assertEquals(1, messageGroupStore.getMessageGroupCount());
    assertEquals(0, messageGroupStore.messageGroupSize(DELAYER_MESSAGE_GROUP_ID));
}
Also used : MessageGroupStore(org.springframework.integration.store.MessageGroupStore) SimpleMessageStore(org.springframework.integration.store.SimpleMessageStore) MessageGroup(org.springframework.integration.store.MessageGroup) BeanFactory(org.springframework.beans.factory.BeanFactory) Test(org.junit.Test)

Example 8 with MessageGroup

use of org.springframework.integration.store.MessageGroup in project spring-integration by spring-projects.

the class AbstractCorrelatingMessageHandler method forceComplete.

protected void forceComplete(MessageGroup group) {
    Object correlationKey = group.getGroupId();
    // UUIDConverter is no-op if already converted
    Lock lock = this.lockRegistry.obtain(UUIDConverter.getUUID(correlationKey).toString());
    boolean removeGroup = true;
    try {
        lock.lockInterruptibly();
        try {
            ScheduledFuture<?> scheduledFuture = this.expireGroupScheduledFutures.remove(UUIDConverter.getUUID(correlationKey));
            if (scheduledFuture != null) {
                boolean canceled = scheduledFuture.cancel(false);
                if (canceled && this.logger.isDebugEnabled()) {
                    this.logger.debug("Cancel 'forceComplete' scheduling for MessageGroup [ " + group + "].");
                }
            }
            MessageGroup groupNow = group;
            /*
				 * If the group argument is not already complete,
				 * re-fetch it because it might have changed while we were waiting on
				 * its lock. If the last modified timestamp changed, defer the completion
				 * because the selection condition may have changed such that the group
				 * would no longer be eligible. If the timestamp changed, it's a completely new
				 * group and should not be reaped on this cycle.
				 *
				 * If the group argument is already complete, do not re-fetch.
				 * Note: not all message stores provide a direct reference to its internal
				 * group so the initial 'isComplete()` will only return true for those stores if
				 * the group was already complete at the time of its selection as a candidate.
				 *
				 * If the group is marked complete, only consider it
				 * for reaping if it's empty (and both timestamps are unaltered).
				 */
            if (!group.isComplete()) {
                groupNow = this.messageStore.getMessageGroup(correlationKey);
            }
            long lastModifiedNow = groupNow.getLastModified();
            int groupSize = groupNow.size();
            if ((!groupNow.isComplete() || groupSize == 0) && group.getLastModified() == lastModifiedNow && group.getTimestamp() == groupNow.getTimestamp()) {
                if (groupSize > 0) {
                    if (this.releaseStrategy.canRelease(groupNow)) {
                        completeGroup(correlationKey, groupNow);
                    } else {
                        expireGroup(correlationKey, groupNow);
                    }
                    if (!this.expireGroupsUponTimeout) {
                        afterRelease(groupNow, groupNow.getMessages(), true);
                        removeGroup = false;
                    }
                } else {
                    /*
						 * By default empty groups are removed on the same schedule as non-empty
						 * groups. A longer timeout for empty groups can be enabled by
						 * setting minimumTimeoutForEmptyGroups.
						 */
                    removeGroup = lastModifiedNow <= (System.currentTimeMillis() - this.minimumTimeoutForEmptyGroups);
                    if (removeGroup && this.logger.isDebugEnabled()) {
                        this.logger.debug("Removing empty group: " + correlationKey);
                    }
                }
            } else {
                removeGroup = false;
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Group expiry candidate (" + correlationKey + ") has changed - it may be reconsidered for a future expiration");
                }
            }
        } catch (MessageDeliveryException e) {
            removeGroup = false;
            if (this.logger.isDebugEnabled()) {
                this.logger.debug("Group expiry candidate (" + correlationKey + ") has been affected by MessageDeliveryException - " + "it may be reconsidered for a future expiration one more time");
            }
            throw e;
        } finally {
            try {
                if (removeGroup) {
                    this.remove(group);
                }
            } finally {
                lock.unlock();
            }
        }
    } catch (InterruptedException ie) {
        Thread.currentThread().interrupt();
        this.logger.debug("Thread was interrupted while trying to obtain lock");
    }
}
Also used : MessageGroup(org.springframework.integration.store.MessageGroup) SimpleMessageGroup(org.springframework.integration.store.SimpleMessageGroup) MessageDeliveryException(org.springframework.messaging.MessageDeliveryException) Lock(java.util.concurrent.locks.Lock)

Example 9 with MessageGroup

use of org.springframework.integration.store.MessageGroup in project spring-integration by spring-projects.

the class AbstractCorrelatingMessageHandler method scheduleGroupToForceComplete.

private void scheduleGroupToForceComplete(Object groupId) {
    MessageGroup messageGroup = this.messageStore.getMessageGroup(groupId);
    scheduleGroupToForceComplete(messageGroup);
}
Also used : MessageGroup(org.springframework.integration.store.MessageGroup) SimpleMessageGroup(org.springframework.integration.store.SimpleMessageGroup)

Example 10 with MessageGroup

use of org.springframework.integration.store.MessageGroup in project spring-integration by spring-projects.

the class AbstractCorrelatingMessageHandler method handleMessageInternal.

@Override
protected void handleMessageInternal(Message<?> message) throws Exception {
    Object correlationKey = this.correlationStrategy.getCorrelationKey(message);
    Assert.state(correlationKey != null, "Null correlation not allowed.  Maybe the CorrelationStrategy is failing?");
    if (this.logger.isDebugEnabled()) {
        this.logger.debug("Handling message with correlationKey [" + correlationKey + "]: " + message);
    }
    UUID groupIdUuid = UUIDConverter.getUUID(correlationKey);
    Lock lock = this.lockRegistry.obtain(groupIdUuid.toString());
    lock.lockInterruptibly();
    try {
        ScheduledFuture<?> scheduledFuture = this.expireGroupScheduledFutures.remove(groupIdUuid);
        if (scheduledFuture != null) {
            boolean canceled = scheduledFuture.cancel(true);
            if (canceled && this.logger.isDebugEnabled()) {
                this.logger.debug("Cancel 'ScheduledFuture' for MessageGroup with Correlation Key [ " + correlationKey + "].");
            }
        }
        MessageGroup messageGroup = this.messageStore.getMessageGroup(correlationKey);
        if (this.sequenceAware) {
            messageGroup = new SequenceAwareMessageGroup(messageGroup);
        }
        if (!messageGroup.isComplete() && messageGroup.canAdd(message)) {
            if (this.logger.isTraceEnabled()) {
                this.logger.trace("Adding message to group [ " + messageGroup + "]");
            }
            messageGroup = this.store(correlationKey, message);
            if (this.releaseStrategy.canRelease(messageGroup)) {
                Collection<Message<?>> completedMessages = null;
                try {
                    completedMessages = this.completeGroup(message, correlationKey, messageGroup);
                } finally {
                    // Possible clean (implementation dependency) up
                    // even if there was an exception processing messages
                    afterRelease(messageGroup, completedMessages);
                }
                if (!isExpireGroupsUponCompletion() && this.minimumTimeoutForEmptyGroups > 0) {
                    removeEmptyGroupAfterTimeout(messageGroup, this.minimumTimeoutForEmptyGroups);
                }
            } else {
                scheduleGroupToForceComplete(messageGroup);
            }
        } else {
            discardMessage(message);
        }
    } finally {
        lock.unlock();
    }
}
Also used : Message(org.springframework.messaging.Message) MessageGroup(org.springframework.integration.store.MessageGroup) SimpleMessageGroup(org.springframework.integration.store.SimpleMessageGroup) UUID(java.util.UUID) Lock(java.util.concurrent.locks.Lock)

Aggregations

MessageGroup (org.springframework.integration.store.MessageGroup)98 Test (org.junit.Test)79 SimpleMessageGroup (org.springframework.integration.store.SimpleMessageGroup)54 GenericMessage (org.springframework.messaging.support.GenericMessage)36 MessageGroupStore (org.springframework.integration.store.MessageGroupStore)25 Message (org.springframework.messaging.Message)20 ArrayList (java.util.ArrayList)19 RedisAvailable (org.springframework.integration.redis.rules.RedisAvailable)15 RedisConnectionFactory (org.springframework.data.redis.connection.RedisConnectionFactory)14 MongoDbAvailable (org.springframework.integration.mongodb.rules.MongoDbAvailable)13 AbstractBatchingMessageGroupStore (org.springframework.integration.store.AbstractBatchingMessageGroupStore)13 MongoClient (com.mongodb.MongoClient)12 SimpleMongoDbFactory (org.springframework.data.mongodb.core.SimpleMongoDbFactory)12 Transactional (org.springframework.transaction.annotation.Transactional)10 LinkedList (java.util.LinkedList)8 List (java.util.List)7 Matchers.containsString (org.hamcrest.Matchers.containsString)7 UUID (java.util.UUID)6 DirectFieldAccessor (org.springframework.beans.DirectFieldAccessor)6 HashMap (java.util.HashMap)5