INTERIM INT-266: API for CorrelationStrategy provided. Namespace/annotation support needs to follow.
This commit is contained in:
@@ -62,8 +62,8 @@ public abstract class AbstractMessageAggregator extends
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MessageBarrier<Map<Object, Message<?>>, Object> createMessageBarrier() {
|
||||
return new MessageBarrier<Map<Object, Message<?>>, Object>(new LinkedHashMap<Object, Message<?>>());
|
||||
protected MessageBarrier<Map<Object, Message<?>>, Object> createMessageBarrier(Object correlationKey) {
|
||||
return new MessageBarrier<Map<Object, Message<?>>, Object>(new LinkedHashMap<Object, Message<?>>(), correlationKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,12 +75,12 @@ public abstract class AbstractMessageAggregator extends
|
||||
}
|
||||
}
|
||||
if (barrier.isComplete()) {
|
||||
this.removeBarrier(barrier.getCorrelationId());
|
||||
this.removeBarrier(barrier.getCorrelationKey());
|
||||
Message<?> result = this.aggregateMessages(messageList);
|
||||
if (result != null) {
|
||||
if (result.getHeaders().getCorrelationId() == null) {
|
||||
result = MessageBuilder.fromMessage(result)
|
||||
.setCorrelationId(barrier.getCorrelationId())
|
||||
.setCorrelationId(barrier.getCorrelationKey())
|
||||
.build();
|
||||
}
|
||||
this.sendReply(result, this.resolveReplyChannelFromMessage(messageList.get(0)));
|
||||
|
||||
@@ -111,8 +111,10 @@ public abstract class AbstractMessageBarrierHandler<T extends Map<K, Message<?>>
|
||||
|
||||
private final Object lifecycleMonitor = new Object();
|
||||
|
||||
private CorrelationStrategy correlationStrategy = new HeaderAttributeCorrelationStrategy(MessageHeaders.CORRELATION_ID);
|
||||
|
||||
public AbstractMessageBarrierHandler() {
|
||||
|
||||
public AbstractMessageBarrierHandler() {
|
||||
this.channelTemplate.setSendTimeout(DEFAULT_SEND_TIMEOUT);
|
||||
}
|
||||
|
||||
@@ -181,7 +183,11 @@ public abstract class AbstractMessageBarrierHandler<T extends Map<K, Message<?>>
|
||||
}
|
||||
}
|
||||
|
||||
public final void afterPropertiesSet() {
|
||||
public void setCorrelationStrategy(CorrelationStrategy correlationStrategy) {
|
||||
this.correlationStrategy = correlationStrategy;
|
||||
}
|
||||
|
||||
public final void afterPropertiesSet() {
|
||||
synchronized (this.lifecycleMonitor) {
|
||||
if (!this.initialized) {
|
||||
this.trackedCorrelationIds = new ArrayBlockingQueue<Object>(this.trackedCorrelationIdCapacity);
|
||||
@@ -223,20 +229,20 @@ public abstract class AbstractMessageBarrierHandler<T extends Map<K, Message<?>>
|
||||
if (!this.initialized) {
|
||||
this.afterPropertiesSet();
|
||||
}
|
||||
Object correlationId = message.getHeaders().getCorrelationId();
|
||||
if (correlationId == null) {
|
||||
Object correlationKey = this.correlationStrategy.getCorrelationKey(message);
|
||||
if (correlationKey == null) {
|
||||
throw new MessageHandlingException(message, this.getClass().getSimpleName()
|
||||
+ " requires the 'correlationId' property");
|
||||
+ " requires the 'correlationKey' property");
|
||||
}
|
||||
if (this.trackedCorrelationIds.contains(correlationId)) {
|
||||
if (this.trackedCorrelationIds.contains(correlationKey)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Handling of Message group with correlationId '" + correlationId
|
||||
logger.debug("Handling of Message group with correlationKey '" + correlationKey
|
||||
+ "' has already completed or timed out.");
|
||||
}
|
||||
this.discardMessage(message);
|
||||
}
|
||||
else {
|
||||
this.processMessage(message, correlationId);
|
||||
this.processMessage(message, correlationKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,10 +255,10 @@ public abstract class AbstractMessageBarrierHandler<T extends Map<K, Message<?>>
|
||||
}
|
||||
}
|
||||
|
||||
private void processMessage(Message<?> message, Object correlationId) {
|
||||
MessageBarrier<T,K> barrier = barriers.putIfAbsent(correlationId, createMessageBarrier());
|
||||
private void processMessage(Message<?> message, Object correlationKey) {
|
||||
MessageBarrier<T,K> barrier = barriers.putIfAbsent(correlationKey, createMessageBarrier(correlationKey));
|
||||
if (barrier == null) {
|
||||
barrier = barriers.get(message.getHeaders().getCorrelationId());
|
||||
barrier = barriers.get(correlationKey);
|
||||
}
|
||||
synchronized (barrier) {
|
||||
if (canAddMessage(message, barrier)) {
|
||||
@@ -335,7 +341,7 @@ public abstract class AbstractMessageBarrierHandler<T extends Map<K, Message<?>>
|
||||
/**
|
||||
* Factory method for creating a MessageBarrier implementation.
|
||||
*/
|
||||
protected abstract MessageBarrier<T, K> createMessageBarrier();
|
||||
protected abstract MessageBarrier<T, K> createMessageBarrier(Object correlationKey);
|
||||
|
||||
/**
|
||||
* A method for processing the information in the message barrier after a message has been added or on pruning.
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aggregator;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
|
||||
/**
|
||||
* Strategy for determining how messages shall be correlated. Implementations
|
||||
* shall return the correlation key value associated with a particular message.
|
||||
*
|
||||
* @author: Marius Bogoevici
|
||||
*/
|
||||
public interface CorrelationStrategy {
|
||||
|
||||
Object getCorrelationKey(Message<?> message);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aggregator;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
|
||||
/**
|
||||
* Default implementation of {@link CorrelationStrategy}. Uses a header
|
||||
* attribute to determine the correlation key value.
|
||||
*
|
||||
* @author: Marius Bogoevici
|
||||
*/
|
||||
public class HeaderAttributeCorrelationStrategy implements CorrelationStrategy {
|
||||
|
||||
private String attributeName;
|
||||
|
||||
|
||||
public HeaderAttributeCorrelationStrategy(String attributeName) {
|
||||
this.attributeName = attributeName;
|
||||
}
|
||||
|
||||
|
||||
public Object getCorrelationKey(Message<?> message) {
|
||||
return message.getHeaders().get(this.attributeName);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,18 +39,17 @@ public class MessageBarrier<T extends Map<K, Message<?>>, K> {
|
||||
|
||||
private volatile boolean complete = false;
|
||||
|
||||
private Object correlationKey;
|
||||
|
||||
private final long timestamp = System.currentTimeMillis();
|
||||
|
||||
public MessageBarrier(T messages) {
|
||||
public MessageBarrier(T messages, Object correlationKey) {
|
||||
this.messages = messages;
|
||||
this.correlationKey = correlationKey;
|
||||
}
|
||||
|
||||
public Object getCorrelationId() {
|
||||
if (!messages.isEmpty()) {
|
||||
return messages.values().iterator().next().getHeaders()
|
||||
.getCorrelationId();
|
||||
}
|
||||
return null;
|
||||
public Object getCorrelationKey() {
|
||||
return this.correlationKey;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,9 +50,9 @@ public class Resequencer extends AbstractMessageBarrierHandler<SortedMap<Integer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MessageBarrier<SortedMap<Integer, Message<?>>, Integer> createMessageBarrier() {
|
||||
protected MessageBarrier<SortedMap<Integer, Message<?>>, Integer> createMessageBarrier(Object correlationKey) {
|
||||
MessageBarrier<SortedMap<Integer, Message<?>>, Integer> messageBarrier
|
||||
= new MessageBarrier<SortedMap<Integer, Message<?>>, Integer>(new TreeMap<Integer, Message<?>>());
|
||||
= new MessageBarrier<SortedMap<Integer, Message<?>>, Integer>(new TreeMap<Integer, Message<?>>(), correlationKey);
|
||||
messageBarrier.getMessages().put(0, createFlagMessage(0));
|
||||
return messageBarrier;
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class Resequencer extends AbstractMessageBarrierHandler<SortedMap<Integer
|
||||
if (!CollectionUtils.isEmpty(releasedMessages)) {
|
||||
Message<?> lastMessage = releasedMessages.get(releasedMessages.size()-1);
|
||||
if (lastMessage.getHeaders().getSequenceNumber().equals(lastMessage.getHeaders().getSequenceSize() - 1)) {
|
||||
this.removeBarrier(barrier.getCorrelationId());
|
||||
this.removeBarrier(barrier.getCorrelationKey());
|
||||
}
|
||||
this.sendReplies(releasedMessages, this.resolveReplyChannelFromMessage(releasedMessages.get(0)));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2002-2008 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.aggregator;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.core.MessageHeaders;
|
||||
import org.springframework.integration.message.MessageBuilder;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* @author: Marius Bogoevici
|
||||
*/
|
||||
public class HeaderAttributeCorrelationStrategyTests {
|
||||
|
||||
@Test
|
||||
public void testHeaderAttributeCorrelationStrategy() {
|
||||
String testedHeaderValue = "@!arbitraryTestValue!@";
|
||||
String testHeaderName = "header.for.test";
|
||||
Message message = MessageBuilder.withPayload("irrelevantData").setHeader(testHeaderName, testedHeaderValue).build();
|
||||
HeaderAttributeCorrelationStrategy correlationStrategy = new HeaderAttributeCorrelationStrategy(testHeaderName);
|
||||
assertEquals(testedHeaderValue, correlationStrategy.getCorrelationKey(message));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -32,7 +32,7 @@ public class MessageBarrierTests {
|
||||
|
||||
@Test
|
||||
public void testMessageRetrieval() {
|
||||
MessageBarrier barrier = new MessageBarrier(new LinkedHashMap());
|
||||
MessageBarrier barrier = new MessageBarrier(new LinkedHashMap(), null);
|
||||
barrier.getMessages().put("1", new StringMessage("test1"));
|
||||
assertEquals(1, barrier.getMessages().size());
|
||||
barrier.getMessages().put("2", new StringMessage("test2"));
|
||||
@@ -42,7 +42,7 @@ public class MessageBarrierTests {
|
||||
@Test
|
||||
public void testTimestamp() {
|
||||
long before = System.currentTimeMillis();
|
||||
MessageBarrier barrier = new MessageBarrier(new LinkedHashMap());
|
||||
MessageBarrier barrier = new MessageBarrier(new LinkedHashMap(), null);
|
||||
long timestamp = barrier.getTimestamp();
|
||||
assertTrue(before <= timestamp);
|
||||
long after = System.currentTimeMillis();
|
||||
@@ -51,7 +51,7 @@ public class MessageBarrierTests {
|
||||
|
||||
@Test
|
||||
public void testEmptyMessageList() {
|
||||
MessageBarrier barrier = new MessageBarrier(new LinkedHashMap());
|
||||
MessageBarrier barrier = new MessageBarrier(new LinkedHashMap(), null);
|
||||
assertEquals(0, barrier.getMessages().size());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user