diff --git a/org.springframework.integration.ws/src/main/java/org/springframework/integration/ws/AbstractWebServiceOutboundGateway.java b/org.springframework.integration.ws/src/main/java/org/springframework/integration/ws/AbstractWebServiceOutboundGateway.java index 6c500e82e1..b2a0f6ff49 100644 --- a/org.springframework.integration.ws/src/main/java/org/springframework/integration/ws/AbstractWebServiceOutboundGateway.java +++ b/org.springframework.integration.ws/src/main/java/org/springframework/integration/ws/AbstractWebServiceOutboundGateway.java @@ -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 true. Set this to false 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); + } } } diff --git a/org.springframework.integration.ws/src/main/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParser.java b/org.springframework.integration.ws/src/main/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParser.java index 4b8c6c7fa2..e1cd8e9655 100644 --- a/org.springframework.integration.ws/src/main/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParser.java +++ b/org.springframework.integration.ws/src/main/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParser.java @@ -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 <outbound-gateway/> 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); diff --git a/org.springframework.integration.ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-1.0.xsd b/org.springframework.integration.ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-1.0.xsd index b3585754d2..90ff1a6575 100644 --- a/org.springframework.integration.ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-1.0.xsd +++ b/org.springframework.integration.ws/src/main/resources/org/springframework/integration/ws/config/spring-integration-ws-1.0.xsd @@ -75,7 +75,15 @@ - + + + + + + diff --git a/org.springframework.integration.ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java b/org.springframework.integration.ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java index 4af9ca93f2..ff67bdc025 100644 --- a/org.springframework.integration.ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java +++ b/org.springframework.integration.ws/src/test/java/org/springframework/integration/ws/config/WebServiceOutboundGatewayParserTests.java @@ -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( diff --git a/org.springframework.integration.ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml b/org.springframework.integration.ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml index 3d07d90a80..44536d562b 100644 --- a/org.springframework.integration.ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml +++ b/org.springframework.integration.ws/src/test/java/org/springframework/integration/ws/config/simpleWebServiceOutboundGatewayParserTests.xml @@ -19,6 +19,20 @@ + + + + + + + +