GH-3180: Add encoding-mode to WS outbound gateway (#3191)

* GH-3180: Add encoding-mode to WS outbound gateway

Fixes https://github.com/spring-projects/spring-integration/issues/3180

* Deprecate `encode-uri` in favor of newly introduced `encoding-mode`
* Add new property to XML and DSL configurations
* Fix tests according a new behavior
* Document the feature
* Fix docs for deprecated `encode-uri`
* Mention also WS from `http.adoc`

* * Fix typos in docs
This commit is contained in:
Artem Bilan
2020-02-21 16:47:42 -05:00
committed by GitHub
parent b38c9e16e8
commit 50ac603d6c
12 changed files with 135 additions and 87 deletions

View File

@@ -18,7 +18,6 @@ package org.springframework.integration.ws;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
@@ -35,8 +34,7 @@ import org.springframework.messaging.MessageDeliveryException;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
@@ -60,11 +58,13 @@ import org.springframework.xml.transform.TransformerObjectSupport;
*/
public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyProducingMessageHandler {
protected final DefaultUriBuilderFactory uriFactory = new DefaultUriBuilderFactory(); // NOSONAR - final
private final String uri;
private final DestinationProvider destinationProvider;
private final Map<String, Expression> uriVariableExpressions = new HashMap<String, Expression>();
private final Map<String, Expression> uriVariableExpressions = new HashMap<>();
private StandardEvaluationContext evaluationContext;
@@ -74,8 +74,6 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
private boolean ignoreEmptyResponses = true;
private boolean encodeUri = true;
private SoapHeaderMapper headerMapper = new DefaultSoapHeaderMapper();
private boolean webServiceTemplateExplicitlySet;
@@ -89,6 +87,7 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
public AbstractWebServiceOutboundGateway(DestinationProvider destinationProvider,
WebServiceMessageFactory messageFactory) {
Assert.notNull(destinationProvider, "DestinationProvider must not be null");
this.webServiceTemplate = new WebServiceTemplate(messageFactory);
this.destinationProvider = destinationProvider;
@@ -99,6 +98,7 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
}
public void setHeaderMapper(SoapHeaderMapper headerMapper) {
Assert.notNull(headerMapper, "'headerMapper' must not be null");
this.headerMapper = headerMapper;
}
@@ -120,13 +120,29 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
* @param encodeUri true if the URI should be encoded.
* @see org.springframework.web.util.UriComponentsBuilder
* @since 4.1
* @deprecated since 5.3 in favor of {@link #setEncodingMode}
*/
@Deprecated
public void setEncodeUri(boolean encodeUri) {
this.encodeUri = encodeUri;
setEncodingMode(
encodeUri
? DefaultUriBuilderFactory.EncodingMode.TEMPLATE_AND_VALUES
: DefaultUriBuilderFactory.EncodingMode.NONE);
}
/**
* Set the encoding mode to use.
* By default this is set to {@link DefaultUriBuilderFactory.EncodingMode#TEMPLATE_AND_VALUES}.
* @param encodingMode the mode to use for uri encoding
* @since 5.3
*/
public void setEncodingMode(DefaultUriBuilderFactory.EncodingMode encodingMode) {
Assert.notNull(encodingMode, "'encodingMode' must not be null");
this.uriFactory.setEncodingMode(encodingMode);
}
public void setReplyChannel(MessageChannel replyChannel) {
this.setOutputChannel(replyChannel);
setOutputChannel(replyChannel);
}
/**
@@ -200,40 +216,33 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
@Override
public final Object handleRequestMessage(Message<?> requestMessage) {
URI uriWithVariables = null;
try {
uriWithVariables = this.prepareUri(requestMessage);
}
catch (URISyntaxException e) {
throw new IllegalArgumentException(e);
}
URI uriWithVariables = prepareUri(requestMessage);
if (uriWithVariables == null) {
throw new MessageDeliveryException(requestMessage, "Failed to determine URI for " +
"Web Service request in outbound gateway: " + this.getComponentName());
}
Object responsePayload = this.doHandle(uriWithVariables.toString(), requestMessage, this.requestCallback);
if (responsePayload != null) {
boolean shouldIgnore = (this.ignoreEmptyResponses
&& responsePayload instanceof String && !StringUtils.hasText((String) responsePayload));
if (!shouldIgnore) {
return responsePayload;
}
Object responsePayload = doHandle(uriWithVariables.toString(), requestMessage, this.requestCallback);
if (responsePayload != null && !(this.ignoreEmptyResponses
&& responsePayload instanceof String
&& !StringUtils.hasText((String) responsePayload))) {
return responsePayload;
}
return null;
}
private URI prepareUri(Message<?> requestMessage) throws URISyntaxException {
private URI prepareUri(Message<?> requestMessage) {
if (this.destinationProvider != null) {
return this.destinationProvider.getDestination();
}
Map<String, Object> uriVariables = ExpressionEvalMap.from(this.uriVariableExpressions)
.usingEvaluationContext(this.evaluationContext)
.withRoot(requestMessage)
.build();
Map<String, Object> uriVariables =
ExpressionEvalMap.from(this.uriVariableExpressions)
.usingEvaluationContext(this.evaluationContext)
.withRoot(requestMessage)
.build();
UriComponents uriComponents = UriComponentsBuilder.fromUriString(this.uri).buildAndExpand(uriVariables);
return this.encodeUri ? uriComponents.toUri() : new URI(uriComponents.toUriString());
return this.uriFactory.expand(this.uri, uriVariables);
}
@@ -282,7 +291,7 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
if (resultObject != null && message instanceof SoapMessage) {
Map<String, Object> mappedMessageHeaders =
AbstractWebServiceOutboundGateway.this.headerMapper.toHeadersFromReply((SoapMessage) message);
return AbstractWebServiceOutboundGateway.this.getMessageBuilderFactory()
return getMessageBuilderFactory()
.withPayload(resultObject)
.copyHeaders(mappedMessageHeaders)
.build();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -52,7 +52,7 @@ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayPars
@Override
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(this.getGatewayClassName(element));
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(getGatewayClassName(element));
String uri = element.getAttribute("uri");
String destinationProvider = element.getAttribute("destination-provider");
List<Element> uriVariableElements = DomUtils.getChildElementsByTagName(element, "uri-variable");
@@ -70,7 +70,7 @@ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayPars
else {
builder.addConstructorArgValue(uri);
if (!CollectionUtils.isEmpty(uriVariableElements)) {
ManagedMap<String, Object> uriVariableExpressions = new ManagedMap<String, Object>();
ManagedMap<String, Object> uriVariableExpressions = new ManagedMap<>();
for (Element uriVariableElement : uriVariableElements) {
String name = uriVariableElement.getAttribute("name");
String expression = uriVariableElement.getAttribute("expression");
@@ -87,9 +87,11 @@ public class WebServiceOutboundGatewayParser extends AbstractOutboundGatewayPars
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "requires-reply");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-empty-responses");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encode-uri");
this.postProcessGateway(builder, element, parserContext);
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "encoding-mode");
postProcessGateway(builder, element, parserContext);
IntegrationNamespaceUtils.configureHeaderMapper(element, builder, parserContext, DefaultSoapHeaderMapper.class, null);
IntegrationNamespaceUtils.configureHeaderMapper(element, builder, parserContext,
DefaultSoapHeaderMapper.class, null);
return builder;
}

View File

@@ -24,6 +24,7 @@ import org.springframework.integration.dsl.MessageHandlerSpec;
import org.springframework.integration.util.JavaUtils;
import org.springframework.integration.ws.AbstractWebServiceOutboundGateway;
import org.springframework.integration.ws.SoapHeaderMapper;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.WebServiceMessageCallback;
@@ -39,6 +40,8 @@ import org.springframework.ws.transport.WebServiceMessageSender;
* @param <E> the target {@link AbstractWebServiceOutboundGateway} implementation type.
*
* @author Gary Russell
* @author Artem Bilan
*
* @since 5.3
*
*/
@@ -58,7 +61,7 @@ public abstract class BaseWsOutboundGatewaySpec<
private SoapHeaderMapper headerMapper;
private boolean encodeUri = true;
private DefaultUriBuilderFactory.EncodingMode encodingMode;
private boolean ignoreEmptyResponses = true;
@@ -114,14 +117,12 @@ public abstract class BaseWsOutboundGatewaySpec<
}
/**
* Specify whether the URI should be encoded after any <code>uriVariables</code>
* are expanded and before sending the request. The default value is <code>true</code>.
* @param encodeUri true if the URI should be encoded.
* @return the spec.
* @see org.springframework.web.util.UriComponentsBuilder
* Specify a {@link DefaultUriBuilderFactory.EncodingMode} for uri construction.
* @param encodingMode to use for uri construction.
* @return the spec
*/
public S encodeUri(boolean encodeUri) {
this.encodeUri = encodeUri;
public S encodingMode(DefaultUriBuilderFactory.EncodingMode encodingMode) {
this.encodingMode = encodingMode;
return _this();
}
@@ -158,7 +159,7 @@ public abstract class BaseWsOutboundGatewaySpec<
gateway.setUriVariableExpressions(this.uriVariableExpressions);
JavaUtils.INSTANCE
.acceptIfNotNull(this.headerMapper, gateway::setHeaderMapper);
gateway.setEncodeUri(this.encodeUri);
gateway.setEncodingMode(this.encodingMode);
gateway.setIgnoreEmptyResponses(this.ignoreEmptyResponses);
gateway.setRequestCallback(this.requestCallback);
return gateway;

View File

@@ -127,15 +127,26 @@
<xsd:attribute name="encode-uri" default="true">
<xsd:annotation>
<xsd:documentation>
When set to "false", the URI won't be encoded before the request is sent. This may be useful
[DEPRECATED] When set to "false", the URI won't be encoded before the request is sent. This may be useful
in some scenarios as it allows user control over the encoding, if needed. Default is "true".
This attribute is ignored, if 'destination-provider' is specified.
Deprecated since 5.3 in favor of 'encoding-mode'.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="xsd:boolean xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="encoding-mode" default="TEMPLATE_AND_VALUES">
<xsd:annotation>
<xsd:documentation>
Set the encoding mode during URI building.
</xsd:documentation>
</xsd:annotation>
<xsd:simpleType>
<xsd:union memberTypes="encodingModeEnumeration xsd:string"/>
</xsd:simpleType>
</xsd:attribute>
<xsd:attribute name="destination-provider" type="xsd:string">
<xsd:annotation>
<xsd:documentation>
@@ -531,4 +542,13 @@ this list can also be simple patterns to be matched against the header names (e.
</xsd:attribute>
</xsd:complexType>
<xsd:simpleType name="encodingModeEnumeration">
<xsd:restriction base="xsd:token">
<xsd:enumeration value="TEMPLATE_AND_VALUES"/>
<xsd:enumeration value="VALUES_ONLY"/>
<xsd:enumeration value="URI_COMPONENT"/>
<xsd:enumeration value="NONE"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -42,6 +42,7 @@
<!--Email Transport-->
<ws:outbound-gateway request-channel="inputEmail"
uri="mailto:{to}?subject={subject}"
encoding-mode="VALUES_ONLY"
interceptor="emailInterceptor"
message-sender="emailMessageSender">
<ws:uri-variable name="to" expression="headers.to"/>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -37,8 +37,7 @@ import javax.jms.Session;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.packet.Stanza;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
@@ -52,8 +51,7 @@ import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHandlingException;
import org.springframework.messaging.MessagingException;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.ws.client.WebServiceClientException;
import org.springframework.ws.client.WebServiceIOException;
import org.springframework.ws.client.core.WebServiceMessageCallback;
@@ -74,8 +72,7 @@ import org.springframework.ws.transport.mail.MailSenderConnection;
*
* @since 2.1
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@SpringJUnitConfig
public class UriVariableTests {
@Autowired
@@ -134,7 +131,7 @@ public class UriVariableTests {
assertThatExceptionOfType(MessagingException.class)
.isThrownBy(() -> this.inputHttp.send(message))
.withCauseInstanceOf(WebServiceIOException.class); // offline
assertThat(uri.get()).isEqualTo("http://localhost/spring-integration?param=test1%20&%20test2");
assertThat(uri.get()).isEqualTo("http://localhost/spring-integration?param=test1%20%26%20test2");
}
@Test

View File

@@ -127,7 +127,7 @@
<ws:outbound-gateway id="gatewayWithJmsUri"
request-channel="inputChannel"
encode-uri="false"
encoding-mode="NONE"
uri="jms:wsQueue" />
<bean id="sourceExtractor" class="org.springframework.integration.ws.config.StubSourceExtractor"/>

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -17,6 +17,7 @@
package org.springframework.integration.ws.config;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
@@ -24,8 +25,7 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentMatchers;
import org.springframework.beans.DirectFieldAccessor;
@@ -49,7 +49,8 @@ import org.springframework.messaging.support.GenericMessage;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.scheduling.support.PeriodicTrigger;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.SourceExtractor;
@@ -66,7 +67,7 @@ import org.springframework.ws.transport.WebServiceMessageSender;
* @author Gary Russell
* @author Artem Bilan
*/
@RunWith(SpringRunner.class)
@SpringJUnitConfig
public class WebServiceOutboundGatewayParserTests {
private static volatile int adviceCalled;
@@ -173,7 +174,8 @@ public class WebServiceOutboundGatewayParserTests {
@Test
public void simpleGatewayWithCustomSourceExtractorAndMessageFactory() {
AbstractEndpoint endpoint = context.getBean("gatewayWithCustomSourceExtractorAndMessageFactory", AbstractEndpoint.class);
AbstractEndpoint endpoint = context.getBean("gatewayWithCustomSourceExtractorAndMessageFactory",
AbstractEndpoint.class);
SourceExtractor<?> sourceExtractor = (SourceExtractor<?>) context.getBean("sourceExtractor");
assertThat(endpoint.getClass()).isEqualTo(EventDrivenConsumer.class);
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
@@ -187,7 +189,8 @@ public class WebServiceOutboundGatewayParserTests {
@Test
public void simpleGatewayWithCustomFaultMessageResolver() {
AbstractEndpoint endpoint = this.context.getBean("gatewayWithCustomFaultMessageResolver", AbstractEndpoint.class);
AbstractEndpoint endpoint = this.context.getBean("gatewayWithCustomFaultMessageResolver",
AbstractEndpoint.class);
assertThat(endpoint.getClass()).isEqualTo(EventDrivenConsumer.class);
Object gateway = new DirectFieldAccessor(endpoint).getPropertyValue("handler");
assertThat(gateway.getClass()).isEqualTo(SimpleWebServiceOutboundGateway.class);
@@ -387,7 +390,7 @@ public class WebServiceOutboundGatewayParserTests {
AbstractEndpoint endpoint = this.context.getBean("gatewayWithAdvice", AbstractEndpoint.class);
assertThat(endpoint.getClass()).isEqualTo(EventDrivenConsumer.class);
MessageHandler handler = TestUtils.getPropertyValue(endpoint, "handler", MessageHandler.class);
handler.handleMessage(new GenericMessage<String>("foo"));
handler.handleMessage(new GenericMessage<>("foo"));
assertThat(adviceCalled).isEqualTo(1);
}
@@ -395,18 +398,20 @@ public class WebServiceOutboundGatewayParserTests {
public void testInt2718AdvisedInsideAChain() {
adviceCalled = 0;
MessageChannel channel = context.getBean("gatewayWithAdviceInsideAChain", MessageChannel.class);
channel.send(new GenericMessage<String>("foo"));
channel.send(new GenericMessage<>("foo"));
assertThat(adviceCalled).isEqualTo(1);
}
@Test
@SuppressWarnings("unchecked")
public void jmsUri() {
AbstractEndpoint endpoint = this.context.getBean("gatewayWithJmsUri", AbstractEndpoint.class);
assertThat(endpoint.getClass()).isEqualTo(EventDrivenConsumer.class);
MessageHandler handler = TestUtils.getPropertyValue(endpoint, "handler", MessageHandler.class);
assertThat(TestUtils.getPropertyValue(handler, "destinationProvider")).isNull();
assertThat(TestUtils.getPropertyValue(handler, "encodeUri", Boolean.class)).isFalse();
assertThat(
TestUtils.getPropertyValue(handler, "uriFactory.encodingMode",
DefaultUriBuilderFactory.EncodingMode.class))
.isEqualTo(DefaultUriBuilderFactory.EncodingMode.NONE);
WebServiceTemplate webServiceTemplate = TestUtils.getPropertyValue(handler, "webServiceTemplate",
WebServiceTemplate.class);
@@ -418,23 +423,27 @@ public class WebServiceOutboundGatewayParserTests {
new DirectFieldAccessor(handler).setPropertyValue("webServiceTemplate", webServiceTemplate);
handler.handleMessage(new GenericMessage<String>("foo"));
handler.handleMessage(new GenericMessage<>("foo"));
verify(webServiceTemplate).sendAndReceive(eq("jms:wsQueue"),
any(WebServiceMessageCallback.class),
ArgumentMatchers.<WebServiceMessageExtractor<Object>>any());
}
@Test(expected = BeanDefinitionParsingException.class)
@Test
public void invalidGatewayWithBothUriAndDestinationProvider() {
new ClassPathXmlApplicationContext("invalidGatewayWithBothUriAndDestinationProvider.xml", this.getClass())
.close();
assertThatExceptionOfType(BeanDefinitionParsingException.class)
.isThrownBy(() ->
new ClassPathXmlApplicationContext("invalidGatewayWithBothUriAndDestinationProvider.xml",
getClass()));
}
@Test(expected = BeanDefinitionParsingException.class)
@Test
public void invalidGatewayWithNeitherUriNorDestinationProvider() {
new ClassPathXmlApplicationContext("invalidGatewayWithNeitherUriNorDestinationProvider.xml", this.getClass())
.close();
assertThatExceptionOfType(BeanDefinitionParsingException.class)
.isThrownBy(() ->
new ClassPathXmlApplicationContext("invalidGatewayWithNeitherUriNorDestinationProvider.xml",
getClass()));
}
public static class FooAdvice extends AbstractRequestHandlerAdvice {

View File

@@ -34,6 +34,7 @@ import org.springframework.integration.ws.SimpleWebServiceOutboundGateway;
import org.springframework.integration.ws.SoapHeaderMapper;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.SourceExtractor;
@@ -45,6 +46,8 @@ import org.springframework.ws.transport.WebServiceMessageSender;
/**
* @author Gary Russell
* @author Artem Bilan
*
* @since 5.3
*
*/
@@ -93,7 +96,7 @@ public class WsDslTests {
.marshaller(marshaller)
.unmarshaller(unmarshaller)
.messageFactory(messageFactory)
.encodeUri(true)
.encodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY)
.faultMessageResolver(faultMessageResolver)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
@@ -111,7 +114,7 @@ public class WsDslTests {
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.interceptors", ClientInterceptor[].class)[0])
.isSameAs(interceptor);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.messageSenders",
WebServiceMessageSender[].class)[0])
WebServiceMessageSender[].class)[0])
.isSameAs(messageSender);
assertThat(TestUtils.getPropertyValue(gateway, "requestCallback")).isSameAs(requestCallback);
assertThat(TestUtils.getPropertyValue(gateway, "uriVariableExpressions")).isEqualTo(uriVariableExpressions);
@@ -134,7 +137,7 @@ public class WsDslTests {
.destinationProvider(destinationProvider)
.sourceExtractor(sourceExtractor)
.messageFactory(messageFactory)
.encodeUri(true)
.encodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY)
.faultMessageResolver(faultMessageResolver)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
@@ -151,7 +154,7 @@ public class WsDslTests {
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.interceptors", ClientInterceptor[].class)[0])
.isSameAs(interceptor);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.messageSenders",
WebServiceMessageSender[].class)[0])
WebServiceMessageSender[].class)[0])
.isSameAs(messageSender);
assertThat(TestUtils.getPropertyValue(gateway, "requestCallback")).isSameAs(requestCallback);
assertThat(TestUtils.getPropertyValue(gateway, "uriVariableExpressions")).isEqualTo(uriVariableExpressions);
@@ -169,7 +172,7 @@ public class WsDslTests {
MarshallingWebServiceOutboundGateway gateway =
Ws.marshallingOutboundGateway(template)
.uri(uri)
.encodeUri(true)
.encodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.requestCallback(requestCallback)
@@ -194,7 +197,7 @@ public class WsDslTests {
Ws.simpleOutboundGateway(template)
.uri(uri)
.sourceExtractor(sourceExtractor)
.encodeUri(true)
.encodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.requestCallback(requestCallback)
@@ -205,6 +208,10 @@ public class WsDslTests {
assertThat(TestUtils.getPropertyValue(gateway, "requestCallback")).isSameAs(requestCallback);
assertThat(TestUtils.getPropertyValue(gateway, "uriVariableExpressions")).isEqualTo(uriVariableExpressions);
assertThat(TestUtils.getPropertyValue(gateway, "extractPayload", Boolean.class)).isFalse();
assertThat(
TestUtils.getPropertyValue(gateway, "uriFactory.encodingMode",
DefaultUriBuilderFactory.EncodingMode.class))
.isEqualTo(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY);
}
interface Both extends Marshaller, Unmarshaller {

View File

@@ -715,7 +715,7 @@ If you wish to partially encode some of the URL, use an `expression` within a `<
====
[source,xml]
----
<http:outbound-gateway url="https://somehost/%2f/fooApps?bar={param}" encode-uri="false">
<http:outbound-gateway url="https://somehost/%2f/fooApps?bar={param}" encoding-mode="NONE">
<http:uri-variable name="param"
expression="T(org.apache.commons.httpclient.util.URIUtil)
.encodeWithinQuery('Hello World!')"/>
@@ -724,7 +724,7 @@ If you wish to partially encode some of the URL, use an `expression` within a `<
====
With Java DSL this option can be controlled by the `BaseHttpMessageHandlerSpec.encodingMode()` option.
Same configuration applies for similar outbound components in the <<./webflux.adoc/[webflux,WebFlux module>>.
The same configuration applies for similar outbound components in the <<./webflux.adoc#webflux,WebFlux module>> and <<./ws.adoc#ws,Web Services module>>.
For much sophisticated scenarios it is recommended to configure an `UriTemplateHandler` on the externally provided `RestTemplate`; or in case of WebFlux - `WebClient` with it `UriBuilderFactory`.
[[http-java-config]]

View File

@@ -68,9 +68,11 @@ See <<./amqp.adoc#amqp-inbound-channel-adapter,AMQP Inbound Channel Adapter>>
The `encodeUri` property on the `AbstractHttpRequestExecutingMessageHandler` has been deprecated in favor of newly introduced `encodingMode`.
See `DefaultUriBuilderFactory.EncodingMode` JavaDocs and <<./http.adoc#http-uri-encoding,Controlling URI Encoding>> for more information.
This also affects `WebFluxRequestExecutingMessageHandler`, respective Java DSL and XML configuration.
The same option is added into an `AbstractWebServiceOutboundGateway`.
[[x5.3-ws]]
=== Web Services Changes
Java DSL support has been added for Web Service components.
The `encodeUri` property on the `AbstractWebServiceOutboundGateway` has been deprecated in favor of newly introduced `encodingMode` - similar to HTTP changes above.
See <<./ws.adoc#ws,Web Services Support>> for more information.

View File

@@ -233,7 +233,7 @@ Examples:
.handle(Ws.simpleOutboundGateway(template)
.uri(uri)
.sourceExtractor(sourceExtractor)
.encodeUri(true)
.encodingMode(DefaultUriBuilderFactory.EncodingMode.NONE)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.requestCallback(requestCallback)
@@ -251,7 +251,7 @@ Examples:
.marshaller(marshaller)
.unmarshaller(unmarshaller)
.messageFactory(messageFactory)
.encodeUri(true)
.encodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY)
.faultMessageResolver(faultMessageResolver)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
@@ -267,7 +267,7 @@ Examples:
----
.handle(Ws.marshallingOutboundGateway(template)
.uri(uri)
.encodeUri(true)
.encodingMode(DefaultUriBuilderFactory.EncodingMode.URI_COMPONENT)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.requestCallback(requestCallback)
@@ -305,14 +305,14 @@ If you supply a `DestinationProvider`, variable substitution is not supported an
By default, the URL string is encoded (see https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/util/UriComponentsBuilder.html[`UriComponentsBuilder`]) to the URI object before sending the request.
In some scenarios with a non-standard URI, it is undesirable to perform the encoding.
Since version 4.1, the `<ws:outbound-gateway/>` element provides an `encode-uri` attribute.
To disable encoding the URL, set this attribute `false` (it defaults to `true`).
The `<ws:outbound-gateway/>` element provides an `encoding-mode` attribute.
To disable encoding the URL, set this attribute to `NONE` (by default, it is `TEMPLATE_AND_VALUES`).
If you wish to partially encode some of the URL, you can do so by using an `expression` within a `<uri-variable/>`, as the following example shows:
====
[source,xml]
----
<ws:outbound-gateway url="https://somehost/%2f/fooApps?bar={param}" encode-uri="false">
<ws:outbound-gateway url="https://somehost/%2f/fooApps?bar={param}" encoding-mode="NONE">
<http:uri-variable name="param"
expression="T(org.apache.commons.httpclient.util.URIUtil)
.encodeWithinQuery('Hello World!')"/>
@@ -320,7 +320,7 @@ If you wish to partially encode some of the URL, you can do so by using an `expr
----
====
NOTE: If you set `DestinationProvider`, `encode-uri` is ignored.
NOTE: If you set `DestinationProvider`, `encoding-mode` is ignored.
[[ws-message-headers]]
=== WS Message Headers