INT-1298: Combine some message group features and base classes
This commit is contained in:
@@ -13,20 +13,29 @@
|
||||
|
||||
package org.springframework.integration.aggregator;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
import org.springframework.integration.annotation.Header;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.core.MessagingTemplate;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Base class for MessageGroupProcessor implementations that aggregate the group of Messages into a single Message.
|
||||
@@ -88,4 +97,123 @@ public abstract class AbstractAggregatingMessageGroupProcessor implements Messag
|
||||
|
||||
protected abstract Object aggregatePayloads(MessageGroup group);
|
||||
|
||||
protected MessageListProcessor getAdapter(Object candidate, Class<? extends Annotation> annotationType) {
|
||||
Method method = findAggregatorMethod(candidate, annotationType);
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
return new MethodInvokingMessageListProcessor(candidate, method);
|
||||
}
|
||||
|
||||
private Method findAggregatorMethod(Object candidate, Class<? extends Annotation> annotationType) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(candidate);
|
||||
if (targetClass == null) {
|
||||
targetClass = candidate.getClass();
|
||||
}
|
||||
Method method = this.findAnnotatedMethod(targetClass, annotationType);
|
||||
if (method == null) {
|
||||
method = this.findSinglePublicMethod(targetClass);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
private Method findAnnotatedMethod(final Class<?> targetClass, final Class<? extends Annotation> annotationType) {
|
||||
final AtomicReference<Method> annotatedMethod = new AtomicReference<Method>();
|
||||
ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
|
||||
if (annotation != null) {
|
||||
Assert.isNull(annotatedMethod.get(), "found more than one method on target class [" + targetClass
|
||||
+ "] with the annotation type [" + annotationType.getName() + "]");
|
||||
annotatedMethod.set(method);
|
||||
}
|
||||
}
|
||||
});
|
||||
return annotatedMethod.get();
|
||||
}
|
||||
|
||||
private Method findSinglePublicMethod(Class<?> targetClass) {
|
||||
Set<Method> methods = new HashSet<Method>();
|
||||
for (Method method : targetClass.getMethods()) {
|
||||
if (!method.getDeclaringClass().equals(Object.class)) {
|
||||
methods.add(method);
|
||||
}
|
||||
}
|
||||
removeListIncompatibleMethodsFrom(methods);
|
||||
removeVoidMethodsFrom(methods);
|
||||
removeUnfittingFrom(methods);
|
||||
if (methods.size() > 1) {
|
||||
throw new IllegalArgumentException("Class [" + targetClass + "] contains more than one public Method.");
|
||||
}
|
||||
return methods.isEmpty() ? null : methods.iterator().next();
|
||||
}
|
||||
|
||||
private void removeListIncompatibleMethodsFrom(Set<Method> candidates) {
|
||||
removeMethodsMatchingSelector(candidates, new MethodSelector() {
|
||||
public boolean select(Method method) {
|
||||
int found = 0;
|
||||
for (Class<?> parameterClass : method.getParameterTypes()) {
|
||||
if (Collection.class.isAssignableFrom(parameterClass)) {
|
||||
found++;
|
||||
}
|
||||
}
|
||||
return found != 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeVoidMethodsFrom(Set<Method> candidates) {
|
||||
removeMethodsMatchingSelector(candidates, new MethodSelector() {
|
||||
public boolean select(Method method) {
|
||||
return method.getReturnType().getName().equals("void");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Set<Method> removeUnfittingFrom(Set<Method> candidates) {
|
||||
return removeMethodsMatchingSelector(candidates, new MethodSelector() {
|
||||
public boolean select(Method method) {
|
||||
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
return (!isFittinglyAnnotated(parameterTypes, parameterAnnotations));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isFittinglyAnnotated(Class<?>[] parameterTypes, Annotation[][] parameterAnnotations) {
|
||||
int candidateParametersFound = 0;
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
Class<?> parameterType = parameterTypes[i];
|
||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
boolean headerAnnotationFound = false;
|
||||
for (Annotation annotation : parameterAnnotations[i]) {
|
||||
if (annotation instanceof Header) {
|
||||
headerAnnotationFound = true;
|
||||
}
|
||||
}
|
||||
if (!headerAnnotationFound) {
|
||||
candidateParametersFound++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidateParametersFound == 1;
|
||||
}
|
||||
|
||||
private Set<Method> removeMethodsMatchingSelector(Set<Method> candidates, MethodSelector selector) {
|
||||
Set<Method> removed = new HashSet<Method>();
|
||||
Iterator<Method> iterator = candidates.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Method method = iterator.next();
|
||||
if (selector.select(method)) {
|
||||
iterator.remove();
|
||||
removed.add(method);
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
private interface MethodSelector {
|
||||
boolean select(Method method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
package org.springframework.integration.aggregator;
|
||||
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.integration.core.MessagingTemplate;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
|
||||
@@ -14,20 +15,33 @@ import org.springframework.integration.store.MessageGroup;
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public class ExpressionEvaluatingMessageGroupProcessor extends AbstractExpressionEvaluatingMessageListProcessor
|
||||
implements MessageGroupProcessor {
|
||||
public class ExpressionEvaluatingMessageGroupProcessor extends AbstractAggregatingMessageGroupProcessor implements BeanFactoryAware {
|
||||
|
||||
private final ExpressionEvaluatingMessageListProcessor processor;
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
processor.setBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
processor.setConversionService(conversionService);
|
||||
}
|
||||
|
||||
public void setExpectedType(Class<?> expectedType) {
|
||||
processor.setExpectedType(expectedType);
|
||||
}
|
||||
|
||||
public ExpressionEvaluatingMessageGroupProcessor(String expression) {
|
||||
super(expression);
|
||||
processor = new ExpressionEvaluatingMessageListProcessor(expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the expression provided on the unmarked messages (a collection) in the group, and delegate to the
|
||||
* {@link MessagingTemplate} to send dowstream.
|
||||
*/
|
||||
public void processAndSend(MessageGroup group, MessagingTemplate messagingTemplate, MessageChannel outputChannel) {
|
||||
Object newPayload = process(group.getUnmarked());
|
||||
messagingTemplate.send(outputChannel, MessageBuilder.withPayload(newPayload).build());
|
||||
@Override
|
||||
protected Object aggregatePayloads(MessageGroup group) {
|
||||
return processor.process(group.getUnmarked());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ import org.springframework.integration.transformer.MessageTransformationExceptio
|
||||
* @author Dave Syer
|
||||
* @since 2.0
|
||||
*/
|
||||
public class AbstractExpressionEvaluatingMessageListProcessor implements BeanFactoryAware {
|
||||
public class ExpressionEvaluatingMessageListProcessor implements BeanFactoryAware, MessageListProcessor {
|
||||
|
||||
private final ExpressionParser parser = new SpelExpressionParser(new SpelParserConfiguration(true, true));
|
||||
|
||||
@@ -57,7 +57,7 @@ public class AbstractExpressionEvaluatingMessageListProcessor implements BeanFac
|
||||
/**
|
||||
* Create an {@link ExpressionEvaluatingMessageProcessor} for the given expression String.
|
||||
*/
|
||||
public AbstractExpressionEvaluatingMessageListProcessor(String expression) {
|
||||
public ExpressionEvaluatingMessageListProcessor(String expression) {
|
||||
try {
|
||||
this.expression = parser.parseExpression(expression);
|
||||
this.getEvaluationContext().addPropertyAccessor(new MapAccessor());
|
||||
@@ -116,7 +116,7 @@ public class AbstractExpressionEvaluatingMessageListProcessor implements BeanFac
|
||||
* Processes the Message by evaluating the expression with that Message as the root object. The expression
|
||||
* evaluation result Object will be returned.
|
||||
*/
|
||||
protected Object process(Collection<? extends Message<?>> messages) {
|
||||
public Object process(Collection<? extends Message<?>> messages) {
|
||||
return this.evaluateExpression(this.expression, messages, this.expectedType);
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.springframework.integration.store.MessageGroup;
|
||||
*
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class ExpressionEvaluatingReleaseStrategy extends AbstractExpressionEvaluatingMessageListProcessor implements
|
||||
public class ExpressionEvaluatingReleaseStrategy extends ExpressionEvaluatingMessageListProcessor implements
|
||||
ReleaseStrategy {
|
||||
|
||||
public ExpressionEvaluatingReleaseStrategy(String expression) {
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2010 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 java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.integration.annotation.Header;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* Convenience helper that looks for an appropriate method handling a list of messages and returns null if not found.
|
||||
*
|
||||
* @author Dave Syer
|
||||
*
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MessageListMethodAdapterHelper {
|
||||
|
||||
public MessageListProcessor getAdapter(Object candidate, Class<? extends Annotation> annotationType) {
|
||||
Method method = findAggregatorMethod(candidate, annotationType);
|
||||
if (method == null) {
|
||||
return null;
|
||||
}
|
||||
return new MessageListMethodAdapter(candidate, method);
|
||||
}
|
||||
|
||||
public Method findAggregatorMethod(Object candidate, Class<? extends Annotation> annotationType) {
|
||||
Class<?> targetClass = AopUtils.getTargetClass(candidate);
|
||||
if (targetClass == null) {
|
||||
targetClass = candidate.getClass();
|
||||
}
|
||||
Method method = this.findAnnotatedMethod(targetClass, annotationType);
|
||||
if (method == null) {
|
||||
method = this.findSinglePublicMethod(targetClass);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
private Method findAnnotatedMethod(final Class<?> targetClass, final Class<? extends Annotation> annotationType) {
|
||||
final AtomicReference<Method> annotatedMethod = new AtomicReference<Method>();
|
||||
ReflectionUtils.doWithMethods(targetClass, new ReflectionUtils.MethodCallback() {
|
||||
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
|
||||
Annotation annotation = AnnotationUtils.findAnnotation(method, annotationType);
|
||||
if (annotation != null) {
|
||||
Assert.isNull(annotatedMethod.get(), "found more than one method on target class [" + targetClass
|
||||
+ "] with the annotation type [" + annotationType.getName() + "]");
|
||||
annotatedMethod.set(method);
|
||||
}
|
||||
}
|
||||
});
|
||||
return annotatedMethod.get();
|
||||
}
|
||||
|
||||
private Method findSinglePublicMethod(Class<?> targetClass) {
|
||||
Set<Method> methods = new HashSet<Method>();
|
||||
for (Method method : targetClass.getMethods()) {
|
||||
if (!method.getDeclaringClass().equals(Object.class)) {
|
||||
methods.add(method);
|
||||
}
|
||||
}
|
||||
removeListIncompatibleMethodsFrom(methods);
|
||||
removeVoidMethodsFrom(methods);
|
||||
removeUnfittingFrom(methods);
|
||||
if (methods.size() > 1) {
|
||||
throw new IllegalArgumentException("Class [" + targetClass + "] contains more than one public Method.");
|
||||
}
|
||||
return methods.isEmpty() ? null : methods.iterator().next();
|
||||
}
|
||||
|
||||
private void removeListIncompatibleMethodsFrom(Set<Method> candidates) {
|
||||
removeMethodsMatchingSelector(candidates, new MethodSelector() {
|
||||
public boolean select(Method method) {
|
||||
int found = 0;
|
||||
for (Class<?> parameterClass : method.getParameterTypes()) {
|
||||
if (Collection.class.isAssignableFrom(parameterClass)) {
|
||||
found++;
|
||||
}
|
||||
}
|
||||
return found != 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeVoidMethodsFrom(Set<Method> candidates) {
|
||||
removeMethodsMatchingSelector(candidates, new MethodSelector() {
|
||||
public boolean select(Method method) {
|
||||
return method.getReturnType().getName().equals("void");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Set<Method> removeUnfittingFrom(Set<Method> candidates) {
|
||||
return removeMethodsMatchingSelector(candidates, new MethodSelector() {
|
||||
public boolean select(Method method) {
|
||||
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
return (!isFittinglyAnnotated(parameterTypes, parameterAnnotations));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean isFittinglyAnnotated(Class<?>[] parameterTypes, Annotation[][] parameterAnnotations) {
|
||||
int candidateParametersFound = 0;
|
||||
for (int i = 0; i < parameterTypes.length; i++) {
|
||||
Class<?> parameterType = parameterTypes[i];
|
||||
if (Collection.class.isAssignableFrom(parameterType)) {
|
||||
boolean headerAnnotationFound = false;
|
||||
for (Annotation annotation : parameterAnnotations[i]) {
|
||||
if (annotation instanceof Header) {
|
||||
headerAnnotationFound = true;
|
||||
}
|
||||
}
|
||||
if (!headerAnnotationFound) {
|
||||
candidateParametersFound++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return candidateParametersFound == 1;
|
||||
}
|
||||
|
||||
private Set<Method> removeMethodsMatchingSelector(Set<Method> candidates, MethodSelector selector) {
|
||||
Set<Method> removed = new HashSet<Method>();
|
||||
Iterator<Method> iterator = candidates.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Method method = iterator.next();
|
||||
if (selector.select(method)) {
|
||||
iterator.remove();
|
||||
removed.add(method);
|
||||
}
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
|
||||
private interface MethodSelector {
|
||||
boolean select(Method method);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@ import java.util.Collection;
|
||||
import org.springframework.integration.Message;
|
||||
|
||||
/**
|
||||
* @author dsyer
|
||||
* @author Dave Syer
|
||||
*
|
||||
*/
|
||||
public interface MessageListProcessor {
|
||||
|
||||
@@ -43,7 +43,7 @@ public class MethodInvokingMessageGroupProcessor extends AbstractAggregatingMess
|
||||
* @param target the object to wrap
|
||||
*/
|
||||
public MethodInvokingMessageGroupProcessor(Object target) {
|
||||
this.adapter = new MessageListMethodAdapterHelper().getAdapter(target, Aggregator.class);
|
||||
this.adapter = getAdapter(target, Aggregator.class);
|
||||
Assert.notNull(this.adapter, "No aggregator method could be found for object of type: "+target.getClass());
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public class MethodInvokingMessageGroupProcessor extends AbstractAggregatingMess
|
||||
* @param methodName the name of the method to invoke
|
||||
*/
|
||||
public MethodInvokingMessageGroupProcessor(Object target, String methodName) {
|
||||
this.adapter = new MessageListMethodAdapter(target, methodName);
|
||||
this.adapter = new MethodInvokingMessageListProcessor(target, methodName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ public class MethodInvokingMessageGroupProcessor extends AbstractAggregatingMess
|
||||
* @param method the method to invoke
|
||||
*/
|
||||
public MethodInvokingMessageGroupProcessor(Object target, Method method) {
|
||||
this.adapter = new MessageListMethodAdapter(target, method);
|
||||
this.adapter = new MethodInvokingMessageListProcessor(target, method);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -38,13 +38,13 @@ import org.springframework.util.ReflectionUtils;
|
||||
* @author Iwein Fuld
|
||||
* @author Dave Syer
|
||||
*/
|
||||
public class MessageListMethodAdapter implements MessageListProcessor {
|
||||
public class MethodInvokingMessageListProcessor implements MessageListProcessor {
|
||||
|
||||
private final DefaultMethodInvoker invoker;
|
||||
|
||||
protected final Method method;
|
||||
|
||||
public MessageListMethodAdapter(Object object, String methodName) {
|
||||
public MethodInvokingMessageListProcessor(Object object, String methodName) {
|
||||
Assert.notNull(object, "'object' must not be null");
|
||||
Assert.notNull(methodName, "'methodName' must not be null");
|
||||
this.method = ReflectionUtils.findMethod(object.getClass(), methodName, new Class<?>[]{List.class});
|
||||
@@ -53,7 +53,7 @@ public class MessageListMethodAdapter implements MessageListProcessor {
|
||||
this.invoker = new DefaultMethodInvoker(object, this.method);
|
||||
}
|
||||
|
||||
public MessageListMethodAdapter(Object object, Method method) {
|
||||
public MethodInvokingMessageListProcessor(Object object, Method method) {
|
||||
Assert.notNull(object, "'object' must not be null");
|
||||
Assert.notNull(method, "'method' must not be null");
|
||||
Assert.isTrue(method.getParameterTypes().length == 1
|
||||
@@ -32,15 +32,15 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class MethodInvokingReleaseStrategy implements ReleaseStrategy {
|
||||
|
||||
private final MessageListMethodAdapter adapter;
|
||||
private final MethodInvokingMessageListProcessor adapter;
|
||||
|
||||
public MethodInvokingReleaseStrategy(Object object, Method method) {
|
||||
adapter = new MessageListMethodAdapter(object, method);
|
||||
adapter = new MethodInvokingMessageListProcessor(object, method);
|
||||
this.assertMethodReturnsBoolean();
|
||||
}
|
||||
|
||||
public MethodInvokingReleaseStrategy(Object object, String methodName) {
|
||||
adapter = new MessageListMethodAdapter(object, methodName);
|
||||
adapter = new MethodInvokingMessageListProcessor(object, methodName);
|
||||
this.assertMethodReturnsBoolean();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,12 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.hamcrest.CoreMatchers;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.Factory;
|
||||
import org.hamcrest.Matcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.hamcrest.collection.IsMapContaining;
|
||||
import org.hamcrest.core.IsEqual;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -20,7 +22,7 @@ import org.mockito.Matchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.GenericMessage;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.core.MessagingTemplate;
|
||||
import org.springframework.integration.store.MessageGroup;
|
||||
@@ -45,11 +47,10 @@ public class ExpressionEvaluatingMessageGroupProcessorTests {
|
||||
List<Message<?>> messages = new ArrayList<Message<?>>();
|
||||
|
||||
@Before
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setup() {
|
||||
messages.clear();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
messages.add(new GenericMessage(i + 1));
|
||||
messages.add(MessageBuilder.withPayload(i + 1).setHeader("foo", "bar").build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +62,14 @@ public class ExpressionEvaluatingMessageGroupProcessorTests {
|
||||
verify(outputChannel).send(messageWithPayload(5));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessAndCheckHeaders() throws Exception {
|
||||
when(group.getUnmarked()).thenReturn(messages);
|
||||
processor = new ExpressionEvaluatingMessageGroupProcessor("#root");
|
||||
processor.processAndSend(group, template, outputChannel);
|
||||
verify(outputChannel).send(messageWithHeader("foo", "bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessAndSendWithProjectionExpressionEvaluated() throws Exception {
|
||||
when(group.getUnmarked()).thenReturn(messages);
|
||||
@@ -86,12 +95,16 @@ public class ExpressionEvaluatingMessageGroupProcessorTests {
|
||||
verify(outputChannel).send(messageWithPayload(3 + 4 + 5));
|
||||
}
|
||||
|
||||
private Message<?> messageWithHeader(String key, Object value) {
|
||||
return Matchers.argThat(MessageMatcher.hasHeader(IsMapContaining.hasEntry(key, value)));
|
||||
}
|
||||
|
||||
private Message<?> messageWithPayload(Matcher<?> matcher) {
|
||||
return Matchers.argThat(PayloadMatcher.hasPayload(matcher));
|
||||
return Matchers.argThat(MessageMatcher.hasPayload(matcher));
|
||||
}
|
||||
|
||||
private Message<?> messageWithPayload(int i) {
|
||||
return Matchers.argThat(PayloadMatcher.hasPayload(IsEqual.equalTo(i)));
|
||||
return Matchers.argThat(MessageMatcher.hasPayload(IsEqual.equalTo(i)));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -105,16 +118,19 @@ public class ExpressionEvaluatingMessageGroupProcessorTests {
|
||||
return result;
|
||||
}
|
||||
|
||||
private static class PayloadMatcher extends TypeSafeMatcher<Message<?>> {
|
||||
private static class MessageMatcher extends TypeSafeMatcher<Message<?>> {
|
||||
|
||||
private final Matcher<?> matcher;
|
||||
private final Matcher<?> payloadMatcher;
|
||||
|
||||
private final Matcher<?> headerMatcher;
|
||||
|
||||
/**
|
||||
* @param matcher
|
||||
*/
|
||||
PayloadMatcher(Matcher<?> matcher) {
|
||||
MessageMatcher(Matcher<?> matcher, Matcher<?> headerMatcher) {
|
||||
super();
|
||||
this.matcher = matcher;
|
||||
this.payloadMatcher = matcher;
|
||||
this.headerMatcher = headerMatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -122,7 +138,7 @@ public class ExpressionEvaluatingMessageGroupProcessorTests {
|
||||
*/
|
||||
@Override
|
||||
public boolean matchesSafely(Message<?> message) {
|
||||
return matcher.matches(message.getPayload());
|
||||
return payloadMatcher.matches(message.getPayload()) && headerMatcher.matches(message.getHeaders());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,13 +146,18 @@ public class ExpressionEvaluatingMessageGroupProcessorTests {
|
||||
*/
|
||||
//@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("a Message with payload: ").appendDescriptionOf(matcher);
|
||||
|
||||
description.appendText("a Message with payload: ").appendDescriptionOf(payloadMatcher);
|
||||
description.appendText(" and headers: ").appendDescriptionOf(headerMatcher);
|
||||
}
|
||||
|
||||
@Factory
|
||||
public static <T> Matcher<Message<?>> hasPayload(Matcher<T> payloadMatcher) {
|
||||
return new PayloadMatcher(payloadMatcher);
|
||||
return new MessageMatcher(payloadMatcher, CoreMatchers.anything());
|
||||
}
|
||||
|
||||
@Factory
|
||||
public static <T> Matcher<Message<?>> hasHeader(Matcher<T> headerMatcher) {
|
||||
return new MessageMatcher(CoreMatchers.anything(), headerMatcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.MessageRejectedException;
|
||||
import org.springframework.integration.aggregator.CorrelatingMessageHandler;
|
||||
import org.springframework.integration.aggregator.CorrelationStrategy;
|
||||
import org.springframework.integration.aggregator.MessageListMethodAdapter;
|
||||
import org.springframework.integration.aggregator.MethodInvokingMessageListProcessor;
|
||||
import org.springframework.integration.aggregator.ReleaseStrategy;
|
||||
import org.springframework.integration.aggregator.MethodInvokingReleaseStrategy;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
@@ -114,7 +114,7 @@ public class AggregatorParserTests {
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(consumer);
|
||||
Method expectedMethod = TestAggregatorBean.class.getMethod("createSingleMessageFromGroup", List.class);
|
||||
assertEquals("The MethodInvokingAggregator is not injected with the appropriate aggregation method",
|
||||
expectedMethod, ((MessageListMethodAdapter) new DirectFieldAccessor(accessor
|
||||
expectedMethod, ((MethodInvokingMessageListProcessor) new DirectFieldAccessor(accessor
|
||||
.getPropertyValue("outputProcessor")).getPropertyValue("adapter")).getMethod());
|
||||
assertEquals("The AggregatorEndpoint is not injected with the appropriate ReleaseStrategy instance",
|
||||
releaseStrategy, accessor.getPropertyValue("releaseStrategy"));
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-modules id="moduleCoreId" project-version="1.5.0">
|
||||
<wb-module deploy-name="loanshark">
|
||||
<dependent-module deploy-path="/WEB-INF/lib" handle="module:/resource/spring-integration-ip/spring-integration-ip">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<dependent-module deploy-path="/WEB-INF/lib" handle="module:/resource/spring-integration-stream/spring-integration-stream">
|
||||
<dependency-type>uses</dependency-type>
|
||||
</dependent-module>
|
||||
<property name="context-root" value="loanshark"/>
|
||||
<wb-resource deploy-path="/" source-path="src/main/webapp"/>
|
||||
<property name="java-output-path" value="/target/classes"/>
|
||||
|
||||
Reference in New Issue
Block a user