INT-2478 SimpleMessageStore and Sequence* Headers

Fix AbstractCorrelatingMessageHandler to ignore
Message Sequence information IF a custom release strategy is provided.

INT-2478 polishing based on PR comments.

Rename Test case.
This commit is contained in:
Oleg Zhurakousky
2012-03-20 14:14:41 -04:00
committed by Gary Russell
parent da1887a182
commit aeb7df2ad5
6 changed files with 155 additions and 43 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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
@@ -35,6 +35,7 @@ import org.springframework.integration.store.MessageGroup;
import org.springframework.integration.store.MessageGroupCallback;
import org.springframework.integration.store.MessageGroupStore;
import org.springframework.integration.store.MessageStore;
import org.springframework.integration.store.SimpleMessageGroup;
import org.springframework.integration.store.SimpleMessageStore;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -86,6 +87,8 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH
private final ConcurrentMap<Object, Object> locks = new ConcurrentHashMap<Object, Object>();
private volatile boolean sequenceAware = false;
public AbstractCorrelatingMessageHandler(MessageGroupProcessor processor, MessageGroupStore store,
CorrelationStrategy correlationStrategy, ReleaseStrategy releaseStrategy) {
Assert.notNull(processor);
@@ -96,6 +99,7 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH
new HeaderAttributeCorrelationStrategy(MessageHeaders.CORRELATION_ID) : correlationStrategy;
this.releaseStrategy = releaseStrategy == null ? new SequenceSizeReleaseStrategy() : releaseStrategy;
this.messagingTemplate.setSendTimeout(DEFAULT_SEND_TIMEOUT);
sequenceAware = this.releaseStrategy instanceof SequenceSizeReleaseStrategy;
}
public AbstractCorrelatingMessageHandler(MessageGroupProcessor processor, MessageGroupStore store) {
@@ -124,6 +128,7 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH
public void setReleaseStrategy(ReleaseStrategy releaseStrategy) {
Assert.notNull(releaseStrategy);
this.releaseStrategy = releaseStrategy;
sequenceAware = this.releaseStrategy instanceof SequenceSizeReleaseStrategy;
}
public void setOutputChannel(MessageChannel outputChannel) {
@@ -182,16 +187,20 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH
synchronized (lock) {
MessageGroup messageGroup = messageStore.getMessageGroup(correlationKey);
if (this.sequenceAware){
messageGroup = new SequenceAwareMessageGroup(messageGroup);
}
if (!messageGroup.isComplete() && messageGroup.canAdd(message)) {
if (logger.isTraceEnabled()) {
logger.trace("Adding message to group [ " + messageGroup + "]");
}
messageGroup = store(correlationKey, message);
messageGroup = this.store(correlationKey, message);
if (releaseStrategy.canRelease(messageGroup)) {
Collection<Message<?>> completedMessages = null;
try {
completedMessages = completeGroup(message, correlationKey, messageGroup);
completedMessages = this.completeGroup(message, correlationKey, messageGroup);
}
finally {
// Always clean up even if there was an exception
@@ -210,6 +219,7 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH
}
}
/**
* Allows you to provide additional logic that needs to be performed after the MessageGroup was released.
* @param group
@@ -363,4 +373,43 @@ public abstract class AbstractCorrelatingMessageHandler extends AbstractMessageH
return false;
}
private static class SequenceAwareMessageGroup extends SimpleMessageGroup {
public SequenceAwareMessageGroup(MessageGroup messageGroup) {
super(messageGroup);
}
/**
* This method determines whether messages have been added to this group that supersede the given message based on
* its sequence id. This can be helpful to avoid ending up with sequences larger than their required sequence size
* or sequences that are missing certain sequence numbers.
*/
public boolean canAdd(Message<?> message) {
if (this.size() == 0) {
return true;
}
Integer messageSequenceNumber = message.getHeaders().getSequenceNumber();
if (messageSequenceNumber != null && messageSequenceNumber > 0) {
Integer messageSequenceSize = message.getHeaders().getSequenceSize();
if (!messageSequenceSize.equals(this.getSequenceSize())) {
return false;
}
else {
return !this.containsSequenceNumber(this.getMessages(), messageSequenceNumber);
}
}
return true;
}
private boolean containsSequenceNumber(Collection<Message<?>> messages, Integer messageSequenceNumber) {
for (Message<?> member : messages) {
Integer memberSequenceNumber = member.getHeaders().getSequenceNumber();
if (messageSequenceNumber.equals(memberSequenceNumber)) {
return true;
}
}
return false;
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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.

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 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
@@ -77,7 +77,7 @@ public class SimpleMessageGroup implements MessageGroup {
}
public boolean canAdd(Message<?> message) {
return !isMember(message);
return true;
}
public void add(Message<?> message) {
@@ -136,38 +136,6 @@ public class SimpleMessageGroup implements MessageGroup {
this.messages.clear();
}
/**
* This method determines whether messages have been added to this group that supersede the given message based on
* its sequence id. This can be helpful to avoid ending up with sequences larger than their required sequence size
* or sequences that are missing certain sequence numbers.
*/
private boolean isMember(Message<?> message) {
if (size() == 0) {
return false;
}
Integer messageSequenceNumber = message.getHeaders().getSequenceNumber();
if (messageSequenceNumber != null && messageSequenceNumber > 0) {
Integer messageSequenceSize = message.getHeaders().getSequenceSize();
if (!messageSequenceSize.equals(getSequenceSize())) {
return true;
}
else {
return this.containsSequenceNumber(messages, messageSequenceNumber);
}
}
return false;
}
private boolean containsSequenceNumber(Collection<Message<?>> messages, Integer messageSequenceNumber) {
for (Message<?> member : messages) {
Integer memberSequenceNumber = member.getHeaders().getSequenceNumber();
if (messageSequenceNumber.equals(memberSequenceNumber)) {
return true;
}
}
return false;
}
@Override
public String toString() {
return "SimpleMessageGroup{" +