Removed Splitter interface and added AbstractMessageSplitter base class. The MethodInvokingSplitter is now capable of resolving methods when only an Object is provided to its constructor - either a single method containing the @Splitter annotation or a single public Method as a fallback (or if neither is satisifed, an IllegalArgumentException will be thrown).
This commit is contained in:
@@ -20,8 +20,9 @@ import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.splitter.DefaultMessageSplitter;
|
||||
import org.springframework.integration.splitter.MethodInvokingSplitter;
|
||||
import org.springframework.integration.splitter.SplitterEndpoint;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Parser for the <splitter/> element.
|
||||
@@ -32,12 +33,17 @@ public class SplitterParser extends AbstractEndpointParser {
|
||||
|
||||
@Override
|
||||
protected BeanDefinitionBuilder parseConsumer(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SplitterEndpoint.class);
|
||||
if (element.hasAttribute("ref")) {
|
||||
String adapterBeanName = this.parseAdapter(element, parserContext, MethodInvokingSplitter.class);
|
||||
builder.addConstructorArgReference(adapterBeanName);
|
||||
if (element.hasAttribute(REF_ATTRIBUTE)) {
|
||||
String ref = element.getAttribute(REF_ATTRIBUTE);
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MethodInvokingSplitter.class);
|
||||
builder.addConstructorArgReference(ref);
|
||||
if (StringUtils.hasText(element.getAttribute(METHOD_ATTRIBUTE))) {
|
||||
String method = element.getAttribute(METHOD_ATTRIBUTE);
|
||||
builder.addConstructorArgValue(method);
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
return builder;
|
||||
return BeanDefinitionBuilder.genericBeanDefinition(DefaultMessageSplitter.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import org.springframework.integration.annotation.Splitter;
|
||||
import org.springframework.integration.bus.MessageBus;
|
||||
import org.springframework.integration.message.MessageConsumer;
|
||||
import org.springframework.integration.splitter.MethodInvokingSplitter;
|
||||
import org.springframework.integration.splitter.SplitterEndpoint;
|
||||
|
||||
/**
|
||||
* Post-processor for Methods annotated with {@link Splitter @Splitter}.
|
||||
@@ -38,8 +37,7 @@ public class SplitterAnnotationPostProcessor extends AbstractMethodAnnotationPos
|
||||
|
||||
@Override
|
||||
protected MessageConsumer createConsumer(Object bean, Method method, Splitter annotation) {
|
||||
MethodInvokingSplitter splitter = new MethodInvokingSplitter(bean, method);
|
||||
return new SplitterEndpoint(splitter);
|
||||
return new MethodInvokingSplitter(bean, method);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
|
||||
@@ -20,17 +20,30 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.endpoint.AbstractReplyProducingMessageConsumer;
|
||||
import org.springframework.integration.message.CompositeMessage;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageBuilder;
|
||||
import org.springframework.integration.message.MessageHeaders;
|
||||
|
||||
/**
|
||||
* Base class for Message-splitting consumers.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public abstract class AbstractSplitter implements Splitter {
|
||||
public abstract class AbstractMessageSplitter extends AbstractReplyProducingMessageConsumer {
|
||||
|
||||
public List<Message<?>> split(Message<?> message) {
|
||||
@Override
|
||||
protected final boolean shouldSplitComposite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Message<?> handle(Message<?> message) {
|
||||
Object result = this.splitMessage(message);
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
MessageHeaders requestHeaders = message.getHeaders();
|
||||
List<Message<?>> results = new ArrayList<Message<?>>();
|
||||
if (result instanceof Collection) {
|
||||
@@ -55,11 +68,20 @@ public abstract class AbstractSplitter implements Splitter {
|
||||
if (results.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return results;
|
||||
return new CompositeMessage(results);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses must override this method to split the received Message. The
|
||||
* return value may be a Collection or Array. The individual elements may
|
||||
* be Messages, but it is not necessary. If the elements are not Messages,
|
||||
* each will be provided as the payload of a Message. It is also acceptable
|
||||
* to return a single Object or Message. In that case, a single reply
|
||||
* Message will be produced.
|
||||
*/
|
||||
protected abstract Object splitMessage(Message<?> message);
|
||||
|
||||
|
||||
private Message<?> createSplitMessage(Object item, MessageHeaders requestHeaders, int sequenceNumber, int sequenceSize) {
|
||||
if (item instanceof Message<?>) {
|
||||
return setSplitMessageHeaders(MessageBuilder.fromMessage((Message<?>) item),
|
||||
@@ -23,9 +23,14 @@ import java.util.StringTokenizer;
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* The default Message Splitter implementation. Returns individual Messages
|
||||
* after receiving an array or Collection. If a value is provided for the
|
||||
* 'delimiters' property, then String payloads will be tokenized based on
|
||||
* those delimiters.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class DefaultSplitter extends AbstractSplitter {
|
||||
public class DefaultMessageSplitter extends AbstractMessageSplitter {
|
||||
|
||||
private volatile String delimiters;
|
||||
|
||||
@@ -39,7 +44,7 @@ public class DefaultSplitter extends AbstractSplitter {
|
||||
this.delimiters = delimiters;
|
||||
}
|
||||
|
||||
public Object splitMessage(Message<?> message) {
|
||||
protected final Object splitMessage(Message<?> message) {
|
||||
Object payload = message.getPayload();
|
||||
if (payload instanceof String && this.delimiters != null) {
|
||||
List<String> tokens = new ArrayList<String>();
|
||||
@@ -19,11 +19,15 @@ package org.springframework.integration.splitter;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.integration.annotation.Splitter;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.integration.message.MessageMappingMethodInvoker;
|
||||
import org.springframework.integration.util.DefaultMethodResolver;
|
||||
import org.springframework.integration.util.MethodResolver;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A {@link Splitter} implementation that invokes the specified method
|
||||
* A Message Splitter implementation that invokes the specified method
|
||||
* on the given object. The method's return value will be split if it
|
||||
* is a Collection or Array. If the return value is not a Collection or
|
||||
* Array, then the single Object will be returned as the payload of a
|
||||
@@ -31,7 +35,9 @@ import org.springframework.integration.message.MessageMappingMethodInvoker;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class MethodInvokingSplitter extends AbstractSplitter implements Splitter, InitializingBean {
|
||||
public class MethodInvokingSplitter extends AbstractMessageSplitter implements InitializingBean {
|
||||
|
||||
private final MethodResolver methodResolver = new DefaultMethodResolver(Splitter.class);
|
||||
|
||||
private final MessageMappingMethodInvoker invoker;
|
||||
|
||||
@@ -44,6 +50,14 @@ public class MethodInvokingSplitter extends AbstractSplitter implements Splitter
|
||||
this.invoker = new MessageMappingMethodInvoker(object, methodName);
|
||||
}
|
||||
|
||||
public MethodInvokingSplitter(Object object) {
|
||||
Assert.notNull(object, "object must not be null");
|
||||
Method method = this.methodResolver.findMethod(object.getClass());
|
||||
Assert.notNull(method, "unable to resolve Splitter method on target class ["
|
||||
+ object.getClass() + "]");
|
||||
this.invoker = new MessageMappingMethodInvoker(object, method);
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
this.invoker.afterPropertiesSet();
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* 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.splitter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.message.Message;
|
||||
|
||||
/**
|
||||
* Strategy interface for splitting a single {@link Message}
|
||||
* into multiple Messages.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public interface Splitter {
|
||||
|
||||
List<Message<?>> split(Message<?> message);
|
||||
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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.splitter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.integration.endpoint.AbstractReplyProducingMessageConsumer;
|
||||
import org.springframework.integration.message.CompositeMessage;
|
||||
import org.springframework.integration.message.Message;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
*/
|
||||
public class SplitterEndpoint extends AbstractReplyProducingMessageConsumer {
|
||||
|
||||
private final Splitter splitter;
|
||||
|
||||
|
||||
public SplitterEndpoint() {
|
||||
this(new DefaultSplitter());
|
||||
}
|
||||
|
||||
public SplitterEndpoint(Splitter splitter) {
|
||||
Assert.notNull(splitter, "splitter must not be null");
|
||||
this.splitter = splitter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected boolean shouldSplitComposite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Message<?> handle(Message<?> message) {
|
||||
List<Message<?>> results = this.splitter.split(message);
|
||||
if (results == null || results.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return new CompositeMessage(results);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user