INT-681, INT-710, INT-1181 The <service-activator> element now supports an "expression" attribute as an alternative to "ref" + "method". Added ServiceActivatorFactoryBean, modified parser, updated schema, added ServiceActivator constructor to accept expression string, and provided some basic tests.
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.config;
|
||||
|
||||
import org.springframework.integration.handler.ServiceActivatingHandler;
|
||||
import org.springframework.integration.message.MessageHandler;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* FactoryBean for creating {@link ServiceActivatingHandler} instances.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
public class ServiceActivatorFactoryBean extends AbstractMessageHandlerFactoryBean {
|
||||
|
||||
private volatile Long sendTimeout;
|
||||
|
||||
public void setSendTimeout(Long sendTimeout) {
|
||||
this.sendTimeout = sendTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName) {
|
||||
ServiceActivatingHandler handler = (StringUtils.hasText(targetMethodName))
|
||||
? new ServiceActivatingHandler(targetObject, targetMethodName)
|
||||
: new ServiceActivatingHandler(targetObject);
|
||||
return this.configureHandler(handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
MessageHandler createExpressionEvaluatingHandler(String expression) {
|
||||
Class<?> expectedType = null;
|
||||
return this.configureHandler(new ServiceActivatingHandler(expression, expectedType));
|
||||
}
|
||||
|
||||
private ServiceActivatingHandler configureHandler(ServiceActivatingHandler handler) {
|
||||
if (this.sendTimeout != null) {
|
||||
handler.setSendTimeout(sendTimeout);
|
||||
}
|
||||
return handler;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* 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.
|
||||
@@ -16,43 +16,22 @@
|
||||
|
||||
package org.springframework.integration.config.xml;
|
||||
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for the <service-activator> element.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
*/
|
||||
public class ServiceActivatorParser extends AbstractConsumerEndpointParser {
|
||||
public class ServiceActivatorParser extends AbstractDelegatingConsumerEndpointParser {
|
||||
|
||||
@Override
|
||||
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
BeanComponentDefinition innerHandlerDefinition = IntegrationNamespaceUtils.parseInnerHandlerDefinition(element, parserContext);
|
||||
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
IntegrationNamespaceUtils.BASE_PACKAGE + ".handler.ServiceActivatingHandler");
|
||||
if (innerHandlerDefinition != null){
|
||||
builder.addConstructorArgValue(innerHandlerDefinition);
|
||||
} else {
|
||||
String ref = element.getAttribute(REF_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(ref)) {
|
||||
parserContext.getReaderContext().error("The '" + REF_ATTRIBUTE + "' attribute is required for element "
|
||||
+ IntegrationNamespaceUtils.createElementDescription(element) + ".", element);
|
||||
}
|
||||
builder.addConstructorArgReference(ref);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(element.getAttribute(METHOD_ATTRIBUTE))) {
|
||||
String method = element.getAttribute(METHOD_ATTRIBUTE);
|
||||
builder.getRawBeanDefinition().getConstructorArgumentValues().addGenericArgumentValue(method, "java.lang.String");
|
||||
}
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "send-timeout");
|
||||
return builder;
|
||||
String getFactoryBeanClassName() {
|
||||
return "org.springframework.integration.config.ServiceActivatorFactoryBean";
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean hasDefaultOption() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.integration.handler;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.core.Message;
|
||||
import org.springframework.integration.message.MessageHandlingException;
|
||||
@@ -27,7 +28,7 @@ import org.springframework.integration.message.MessageHandlingException;
|
||||
*/
|
||||
public class ServiceActivatingHandler extends AbstractReplyProducingMessageHandler {
|
||||
|
||||
private final MethodInvokingMessageProcessor processor;
|
||||
private final AbstractMessageProcessor processor;
|
||||
|
||||
|
||||
public ServiceActivatingHandler(final Object object) {
|
||||
@@ -42,6 +43,12 @@ public class ServiceActivatingHandler extends AbstractReplyProducingMessageHandl
|
||||
this.processor = new MethodInvokingMessageProcessor(object, methodName);
|
||||
}
|
||||
|
||||
public ServiceActivatingHandler(String expression, Class<?> expectedType) {
|
||||
ExpressionEvaluatingMessageProcessor eemp = new ExpressionEvaluatingMessageProcessor(expression);
|
||||
eemp.setExpectedType(expectedType);
|
||||
this.processor = eemp;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getComponentType() {
|
||||
@@ -51,6 +58,9 @@ public class ServiceActivatingHandler extends AbstractReplyProducingMessageHandl
|
||||
@Override
|
||||
public final void onInit() {
|
||||
this.processor.setConversionService(this.getConversionService());
|
||||
if (this.processor instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.processor).setBeanFactory(this.getBeanFactory());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -730,7 +730,7 @@
|
||||
default="true" />
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="service-activator" type="innerEndpointDefinitionAware">
|
||||
<xsd:element name="service-activator" type="expressionOrInnerEndpointDefinitionAware">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an endpoint for exposing any bean reference as a service that
|
||||
@@ -2125,7 +2125,13 @@
|
||||
<xsd:complexType name="expressionOrInnerEndpointDefinitionAware">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="innerEndpointDefinitionAware">
|
||||
<xsd:attribute name="expression" type="xsd:string" />
|
||||
<xsd:attribute name="expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
A SpEL expression to be evaluated against the input Message as its root object.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<service-activator input-channel="literalExpressionInput" expression="'foo'"/>
|
||||
|
||||
<service-activator input-channel="beanAsTargetInput" expression="@testBean.caps(payload)"/>
|
||||
|
||||
<service-activator input-channel="beanAsArgumentInput" expression="payload.getSimpleClassName(@testBean)"/>
|
||||
|
||||
<service-activator input-channel="beanInvocationResultInput" expression="payload.concat(@testBean.caps('foo'))"/>
|
||||
|
||||
<beans:bean id="testBean" class="org.springframework.integration.config.xml.ServiceActivatorParserTests$TestBean"/>
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* 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.config.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.gateway.SimpleMessagingGateway;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class ServiceActivatorParserTests {
|
||||
|
||||
@Autowired
|
||||
private MessageChannel literalExpressionInput;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel beanAsTargetInput;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel beanAsArgumentInput;
|
||||
|
||||
@Autowired
|
||||
private MessageChannel beanInvocationResultInput;
|
||||
|
||||
|
||||
@Test
|
||||
public void literalExpression() {
|
||||
Object result = this.sendAndReceive(literalExpressionInput, "hello");
|
||||
assertEquals("foo", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanAsTarget() {
|
||||
Object result = this.sendAndReceive(beanAsTargetInput, "hello");
|
||||
assertEquals("HELLO", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanAsArgument() {
|
||||
Object result = this.sendAndReceive(beanAsArgumentInput, new TestPayload());
|
||||
assertEquals("TestBean", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanInvocationResult() {
|
||||
Object result = this.sendAndReceive(beanInvocationResultInput, "hello");
|
||||
assertEquals("helloFOO", result);
|
||||
}
|
||||
|
||||
|
||||
private Object sendAndReceive(MessageChannel channel, Object payload) {
|
||||
SimpleMessagingGateway gateway = new SimpleMessagingGateway();
|
||||
gateway.setRequestChannel(channel);
|
||||
return gateway.sendAndReceive(payload);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestBean {
|
||||
|
||||
public String caps(String s) {
|
||||
return s.toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class TestPayload {
|
||||
|
||||
public String getSimpleClassName(Object o) {
|
||||
return o.getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user