INT-630 Web Service outbound gateways now support a boolean 'ignore-empty-responses' attribute, and the default value is TRUE.

This commit is contained in:
Mark Fisher
2009-07-01 12:28:10 +00:00
parent d4174e1214
commit 3f1c869035
5 changed files with 103 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 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.
@@ -25,6 +25,7 @@ import org.springframework.integration.handler.AbstractReplyProducingMessageHand
import org.springframework.integration.handler.ReplyMessageHolder;
import org.springframework.integration.ws.destination.MessageAwareDestinationProvider;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
@@ -38,6 +39,7 @@ import org.springframework.ws.transport.WebServiceMessageSender;
* Base class for outbound Web Service-invoking Messaging Gateways.
*
* @author Mark Fisher
* @author Jonas Partner
*/
public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyProducingMessageHandler {
@@ -45,7 +47,9 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
private volatile WebServiceMessageCallback requestCallback;
private final MessageAwareDestinationProvider destinationProvider;
private final MessageAwareDestinationProvider destinationProvider;
private volatile boolean ignoreEmptyResponses = true;
public AbstractWebServiceOutboundGateway(MessageAwareDestinationProvider destinationProvider, WebServiceMessageFactory messageFactory) {
@@ -60,6 +64,15 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
this.setOutputChannel(replyChannel);
}
/**
* Specify whether empty String response payloads should be ignored.
* The default is <code>true</code>. Set this to <code>false</code> if
* you want to send empty String responses in reply Messages.
*/
public void setIgnoreEmptyResponses(boolean ignoreEmptyResponses) {
this.ignoreEmptyResponses = ignoreEmptyResponses;
}
public void setMessageFactory(WebServiceMessageFactory messageFactory) {
this.webServiceTemplate.setMessageFactory(messageFactory);
}
@@ -90,9 +103,14 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
@Override
public final void handleRequestMessage(Message<?> message, ReplyMessageHolder replyHolder) {
Object responsePayload = this.doHandle(message.getPayload(), this.getRequestCallback(message),this.getDestinationProvider().getDestination(message));
Object responsePayload = this.doHandle(message.getPayload(),
this.getRequestCallback(message), this.getDestinationProvider().getDestination(message));
if (responsePayload != null) {
replyHolder.set(responsePayload);
boolean shouldIgnore = (this.ignoreEmptyResponses
&& responsePayload instanceof String && !StringUtils.hasText((String) responsePayload));
if (!shouldIgnore) {
replyHolder.set(responsePayload);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 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.
@@ -21,18 +21,20 @@ import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.adapter.config.AbstractRemotingOutboundGatewayParser;
import org.springframework.integration.ws.destination.MessageAwareDestinationProvider;
import org.springframework.integration.ws.destination.HeaderBasedDestinationProvider;
import org.springframework.integration.ws.destination.FixedUriDestinationProvider;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.util.StringUtils;
/**
* Parser for the &lt;outbound-gateway/&gt; element in the 'ws' namespace.
*
* @author Mark Fisher
* @author Jonas Partner
*/
public class WebServiceOutboundGatewayParser extends AbstractRemotingOutboundGatewayParser {
private static final String BASE_PACKAGE = "org.springframework.integration.ws";
@Override
protected String getGatewayClassName(Element element) {
String simpleClassName = (StringUtils.hasText(element.getAttribute("marshaller"))) ?
@@ -47,38 +49,37 @@ public class WebServiceOutboundGatewayParser extends AbstractRemotingOutboundGat
String destinationProvider = element.getAttribute("destination-provider");
if (StringUtils.hasText(destinationProvider) && (StringUtils.hasText(uri) || StringUtils.hasText(uriHeader))) {
parserContext.getReaderContext().error("The 'uri' and/or 'uri-header' can not be specified if setting destination-provider.", element);
parserContext.getReaderContext().error("The 'uri' and/or 'uri-header' are not allowed if setting destination-provider.", element);
}
if (!StringUtils.hasText(destinationProvider) && !(StringUtils.hasText(uri) || StringUtils.hasText(uriHeader))) {
parserContext.getReaderContext().error("The at least one of 'uri' or 'uri-header' must be specified if not setting destination-provider.", element);
parserContext.getReaderContext().error("At least one of 'uri' or 'uri-header' must be specified if not setting destination-provider.", element);
}
if(StringUtils.hasText(destinationProvider)){
if (StringUtils.hasText(destinationProvider)) {
builder.addConstructorArgReference(destinationProvider);
} else if (StringUtils.hasText(uri) && ! StringUtils.hasText(uriHeader)){
BeanDefinitionBuilder destinationProviderBuilder = BeanDefinitionBuilder.genericBeanDefinition(FixedUriDestinationProvider.class);
}
else if (StringUtils.hasText(uri) && ! StringUtils.hasText(uriHeader)) {
BeanDefinitionBuilder destinationProviderBuilder = BeanDefinitionBuilder.genericBeanDefinition(
BASE_PACKAGE + ".destination.FixedUriDestinationProvider");
destinationProviderBuilder.getBeanDefinition().getConstructorArgumentValues().addIndexedArgumentValue(0, uri);
builder.addConstructorArgValue(destinationProviderBuilder.getBeanDefinition());
}else{
BeanDefinitionBuilder destinationProviderBuilder = BeanDefinitionBuilder.genericBeanDefinition(HeaderBasedDestinationProvider.class);
}
else {
BeanDefinitionBuilder destinationProviderBuilder = BeanDefinitionBuilder.genericBeanDefinition(
BASE_PACKAGE + ".destination.HeaderBasedDestinationProvider");
destinationProviderBuilder.getBeanDefinition().getConstructorArgumentValues().addIndexedArgumentValue(0, uri);
destinationProviderBuilder.getBeanDefinition().getConstructorArgumentValues().addIndexedArgumentValue(1, uriHeader);
builder.addConstructorArgValue(destinationProviderBuilder.getBeanDefinition());
}
}
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getGatewayClassName(element));
this.buildDestinationProvider(element, parserContext,builder);
String replyChannel = element.getAttribute("reply-channel");
if (StringUtils.hasText(replyChannel)) {
builder.addPropertyReference("replyChannel", replyChannel);
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-empty-responses");
this.postProcessGateway(builder, element, parserContext);
return builder;
}
@@ -118,7 +119,7 @@ public class WebServiceOutboundGatewayParser extends AbstractRemotingOutboundGat
String messageSenderListRef = element.getAttribute("message-senders");
if (StringUtils.hasText(messageSenderRef) && StringUtils.hasText(messageSenderListRef)) {
parserContext.getReaderContext().error(
"Only one of message-sender or message-senders should be specified", element);
"Only one of message-sender or message-senders should be specified.", element);
}
if (StringUtils.hasText(messageSenderRef)) {
builder.addPropertyReference("messageSender", messageSenderRef);

View File

@@ -75,7 +75,15 @@
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:attribute>
<xsd:attribute name="ignore-empty-responses" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Indicates whether empty String response payloads should be ignored. The default is TRUE.
Set this to FALSE if you want to send empty String responses in reply Messages.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="source-extractor" type="xsd:string">
<xsd:annotation>
<xsd:appinfo>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 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.
@@ -43,6 +43,43 @@ import org.springframework.ws.transport.WebServiceMessageSender;
*/
public class WebServiceOutboundGatewayParserTests {
@Test
public void simpleGatewayWithReplyChannel() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"simpleWebServiceOutboundGatewayParserTests.xml", this.getClass());
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithReplyChannel");
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
assertEquals(SimpleWebServiceOutboundGateway.class, gateway.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(gateway);
Object expected = context.getBean("outputChannel");
assertEquals(expected, accessor.getPropertyValue("outputChannel"));
}
@Test
public void simpleGatewayWithIgnoreEmptyResponseTrueByDefault() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"simpleWebServiceOutboundGatewayParserTests.xml", this.getClass());
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithReplyChannel");
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
assertEquals(SimpleWebServiceOutboundGateway.class, gateway.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(gateway);
assertEquals(Boolean.TRUE, accessor.getPropertyValue("ignoreEmptyResponses"));
}
@Test
public void simpleGatewayWithIgnoreEmptyResponses() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"simpleWebServiceOutboundGatewayParserTests.xml", this.getClass());
AbstractEndpoint endpoint = (AbstractEndpoint) context.getBean("gatewayWithIgnoreEmptyResponsesFalse");
assertEquals(EventDrivenConsumer.class, endpoint.getClass());
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
assertEquals(SimpleWebServiceOutboundGateway.class, gateway.getClass());
DirectFieldAccessor accessor = new DirectFieldAccessor(gateway);
assertEquals(Boolean.FALSE, accessor.getPropertyValue("ignoreEmptyResponses"));
}
@Test
public void simpleGatewayWithDefaultSourceExtractor() {
ApplicationContext context = new ClassPathXmlApplicationContext(

View File

@@ -19,6 +19,20 @@
<si:queue capacity="10"/>
</si:channel>
<si:channel id="outputChannel">
<si:queue capacity="10"/>
</si:channel>
<ws:outbound-gateway id="gatewayWithReplyChannel"
request-channel="inputChannel"
uri="http://example.org"
reply-channel="outputChannel"/>
<ws:outbound-gateway id="gatewayWithIgnoreEmptyResponsesFalse"
request-channel="inputChannel"
uri="http://example.org"
ignore-empty-responses="false"/>
<ws:outbound-gateway id="gatewayWithDefaultSourceExtractor"
request-channel="inputChannel"
uri="http://example.org"/>