GH-2818: DSL support for -ws module

Resolves https://github.com/spring-projects/spring-integration/issues/2818

* Rework to improve fluency
* reduce the number of factory methods and use a different spec when
  an external WST is provided.
* Docs and address comments
This commit is contained in:
Gary Russell
2020-02-20 14:59:32 -05:00
committed by GitHub
parent 8fb201867c
commit ea8c454d3b
15 changed files with 1145 additions and 16 deletions

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.
@@ -165,10 +165,14 @@ public abstract class AbstractWebServiceOutboundGateway extends AbstractReplyPro
this.webServiceTemplate.setFaultMessageResolver(faultMessageResolver);
}
/**
* Specify the {@link WebServiceMessageSender} to use.
* @param messageSender the sender.
* @deprecated in favor of {@link #setMessageSenders(WebServiceMessageSender...)}
*/
@Deprecated
public void setMessageSender(WebServiceMessageSender messageSender) {
Assert.state(!this.webServiceTemplateExplicitlySet,
() -> "'messageSender' must be specified on the provided: " + this.webServiceTemplate);
this.webServiceTemplate.setMessageSender(messageSender);
setMessageSenders(messageSender);
}
public void setMessageSenders(WebServiceMessageSender... messageSenders) {

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.
@@ -30,13 +30,14 @@ import org.springframework.ws.support.MarshallingUtils;
/**
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Gary Russell
* @since 1.0.2
*/
public class MarshallingWebServiceInboundGateway extends AbstractWebServiceInboundGateway {
private volatile Marshaller marshaller;
private Marshaller marshaller;
private volatile Unmarshaller unmarshaller;
private Unmarshaller unmarshaller;
/**
* Creates a new <code>MarshallingWebServiceInboundGateway</code>.
@@ -58,7 +59,7 @@ public class MarshallingWebServiceInboundGateway extends AbstractWebServiceInbou
* @see #MarshallingWebServiceInboundGateway(Marshaller, Unmarshaller)
*/
public MarshallingWebServiceInboundGateway(Marshaller marshaller) {
Assert.notNull(marshaller, "'marshaller' must no be null");
Assert.notNull(marshaller, "'marshaller' must not be null");
Assert.isInstanceOf(Unmarshaller.class, marshaller, "When using this constructor the provided " +
"Marshaller must also implement Unmarshaller");
this.marshaller = marshaller;
@@ -72,19 +73,19 @@ public class MarshallingWebServiceInboundGateway extends AbstractWebServiceInbou
* @param unmarshaller The unmarshaller.
*/
public MarshallingWebServiceInboundGateway(Marshaller marshaller, Unmarshaller unmarshaller) {
Assert.notNull(marshaller, "'marshaller' must no be null");
Assert.notNull(unmarshaller, "'unmarshaller' must no be null");
Assert.notNull(marshaller, "'marshaller' must not be null");
Assert.notNull(unmarshaller, "'unmarshaller' must not be null");
this.marshaller = marshaller;
this.unmarshaller = unmarshaller;
}
public void setMarshaller(Marshaller marshaller) {
Assert.notNull(marshaller, "'marshaller' must no be null");
Assert.notNull(marshaller, "'marshaller' must not be null");
this.marshaller = marshaller;
}
public void setUnmarshaller(Unmarshaller unmarshaller) {
Assert.notNull(unmarshaller, "'unmarshaller' must no be null");
Assert.notNull(unmarshaller, "'unmarshaller' must not be null");
this.unmarshaller = unmarshaller;
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://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.ws.dsl;
import org.springframework.integration.dsl.MessagingGatewaySpec;
import org.springframework.integration.ws.AbstractWebServiceInboundGateway;
import org.springframework.integration.ws.SoapHeaderMapper;
/**
* Base {@link MessagingGatewaySpec} for web services.
*
* @param <S> the target {@link BaseWsInboundGatewaySpec} implementation type.
* @param <E> the target {@link AbstractWebServiceInboundGateway} implementation type.
*
* @author Gary Russell
* @since 5.3
*
*/
public abstract class BaseWsInboundGatewaySpec<
S extends BaseWsInboundGatewaySpec<S, E>, E extends AbstractWebServiceInboundGateway>
extends MessagingGatewaySpec<S, E> {
/**
* Construct an instance.
*/
protected BaseWsInboundGatewaySpec() {
super(null);
}
/**
* Configure the header mapper.
* @param headerMapper the mapper.
* @return the spec.
*/
public S headerMapper(SoapHeaderMapper headerMapper) {
this.target.setHeaderMapper(headerMapper);
return _this();
}
@Override
protected E doGet() {
return assemble(create());
}
protected abstract E create();
protected E assemble(E gateway) {
return gateway;
}
}

View File

@@ -0,0 +1,167 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://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.ws.dsl;
import java.util.HashMap;
import java.util.Map;
import org.springframework.expression.Expression;
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.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.support.destination.DestinationProvider;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* The base {@link MessageHandlerSpec} for {@link AbstractWebServiceOutboundGateway}s.
*
* @param <S> the target {@link BaseWsOutboundGatewaySpec} implementation type.
* @param <E> the target {@link AbstractWebServiceOutboundGateway} implementation type.
*
* @author Gary Russell
* @since 5.3
*
*/
public abstract class BaseWsOutboundGatewaySpec<
S extends BaseWsOutboundGatewaySpec<S, E>, E extends AbstractWebServiceOutboundGateway>
extends MessageHandlerSpec<S, E> {
private final Map<String, Expression> uriVariableExpressions = new HashMap<>();
protected WebServiceTemplate template; // NOSONAR
protected DestinationProvider destinationProvider; // NOSONAR
protected String uri; // NOSONAR
protected WebServiceMessageFactory webServiceMessageFactory; // NOSONAR
private SoapHeaderMapper headerMapper;
private boolean encodeUri = true;
private boolean ignoreEmptyResponses = true;
private WebServiceMessageCallback requestCallback;
protected FaultMessageResolver faultMessageResolver; // NOSONAR
protected WebServiceMessageSender[] messageSenders; // NOSONAR
protected ClientInterceptor[] gatewayInterceptors; // NOSONAR
protected boolean extractPayload = true; // NOSONAR
/**
* Configure with a destination provider;
* @param destinationProvider the destination provider.
* @return the spec.
*/
public S destinationProvider(DestinationProvider destinationProvider) {
this.destinationProvider = destinationProvider;
return _this();
}
/**
* Configure with a URI.
* @param uri the uri.
* @return the spec.
*/
public S uri(String uri) {
this.uri = uri;
return _this();
}
/**
* Configure the header mapper.
* @param headerMapper the mapper.
* @return the spec.
*/
public S headerMapper(SoapHeaderMapper headerMapper) {
this.headerMapper = headerMapper;
return _this();
}
/**
* Set the Map of URI variable expressions to evaluate against the outbound message
* when replacing the variable placeholders in a URI template.
* @param uriVariableExpressions The URI variable expressions.
* @return the spec.
*/
public S uriVariableExpressions(Map<String, Expression> uriVariableExpressions) {
this.uriVariableExpressions.putAll(uriVariableExpressions);
return _this();
}
/**
* 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
*/
public S encodeUri(boolean encodeUri) {
this.encodeUri = encodeUri;
return _this();
}
/**
* 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.
* @param ignoreEmptyResponses true if empty responses should be ignored.
* @return the spec.
*/
public S ignoreEmptyResponses(boolean ignoreEmptyResponses) {
this.ignoreEmptyResponses = ignoreEmptyResponses;
return _this();
}
/**
* Specify the {@link WebServiceMessageCallback} to use.
* @param requestCallback the call back.
* @return the spec.
*/
public S requestCallback(WebServiceMessageCallback requestCallback) {
this.requestCallback = requestCallback;
return _this();
}
@Override
protected E doGet() {
return assemble(create());
}
protected abstract E create();
protected E assemble(E gateway) {
gateway.setUriVariableExpressions(this.uriVariableExpressions);
JavaUtils.INSTANCE
.acceptIfNotNull(this.headerMapper, gateway::setHeaderMapper);
gateway.setEncodeUri(this.encodeUri);
gateway.setIgnoreEmptyResponses(this.ignoreEmptyResponses);
gateway.setRequestCallback(this.requestCallback);
return gateway;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://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.ws.dsl;
import org.springframework.integration.ws.MarshallingWebServiceInboundGateway;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
/**
* The spec for a {@link MarshallingWebServiceInboundGateway}.
*
* @author Gary Russell
* @since 5.3
*
*/
public class MarshallingWsInboundGatewaySpec extends BaseWsInboundGatewaySpec<MarshallingWsInboundGatewaySpec,
MarshallingWebServiceInboundGateway> {
protected Marshaller gatewayMarshaller; // NOSONAR
protected Unmarshaller gatewayUnmarshaller; // NOSONAR
/**
* Specify a marshaller to use.
* @param marshaller the marshaller.
* @return the spec.
*/
public MarshallingWsInboundGatewaySpec marshaller(Marshaller marshaller) {
this.gatewayMarshaller = marshaller;
return this;
}
/**
* Specify an unmarshaller to use. Required if the {@link #gatewayMarshaller} is not also
* an {@link Unmarshaller}.
* @param unmarshaller the unmarshaller.
* @return the spec.
*/
public MarshallingWsInboundGatewaySpec unmarshaller(Unmarshaller unmarshaller) {
this.gatewayUnmarshaller = unmarshaller;
return this;
}
@Override
protected MarshallingWebServiceInboundGateway create() {
if (this.gatewayUnmarshaller != null) {
return new MarshallingWebServiceInboundGateway(this.gatewayMarshaller, this.gatewayUnmarshaller);
}
else {
return new MarshallingWebServiceInboundGateway(this.gatewayMarshaller);
}
}
}

View File

@@ -0,0 +1,149 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://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.ws.dsl;
import java.util.Arrays;
import org.springframework.integration.ws.MarshallingWebServiceOutboundGateway;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* The spec for a {@link MarshallingWebServiceOutboundGateway}.
*
* @author Gary Russell
* @since 5.3
*
*/
public class MarshallingWsOutboundGatewaySpec extends BaseWsOutboundGatewaySpec<
MarshallingWsOutboundGatewaySpec, MarshallingWebServiceOutboundGateway> {
protected MarshallingWsOutboundGatewaySpec(WebServiceTemplate template) {
this.template = template;
}
@Override
protected MarshallingWebServiceOutboundGateway create() {
if (this.destinationProvider != null) {
return new MarshallingWebServiceOutboundGateway(this.destinationProvider, this.template);
}
else {
return new MarshallingWebServiceOutboundGateway(this.uri, this.template);
}
}
/**
* Spec for a {@link MarshallingWebServiceOutboundGateway} where an external
* {@link WebServiceTemplate} is not provided.
*
*/
public static class MarshallingWsOutboundGatewayNoTemplateSpec extends BaseWsOutboundGatewaySpec<
MarshallingWsOutboundGatewayNoTemplateSpec, MarshallingWebServiceOutboundGateway> {
protected Marshaller gatewayMarshaller;
protected Unmarshaller gatewayUnmarshaller;
/**
* Configure the marshaller to use.
* @param marshaller the marshaller.
* @return the spec.
*/
public MarshallingWsOutboundGatewayNoTemplateSpec marshaller(Marshaller marshaller) {
this.gatewayMarshaller = marshaller;
return this;
}
/**
* Configure the unmarshaller to use.
* @param unmarshaller the unmarshaller.
* @return the spec.
*/
public MarshallingWsOutboundGatewayNoTemplateSpec unmarshaller(Unmarshaller unmarshaller) {
this.gatewayUnmarshaller = unmarshaller;
return this;
}
/**
* Specify the {@link WebServiceMessageFactory} to use.
* @param messageFactory the message factory.
* @return the spec.
*/
public MarshallingWsOutboundGatewayNoTemplateSpec messageFactory(WebServiceMessageFactory messageFactory) {
this.webServiceMessageFactory = messageFactory;
return this;
}
/**
* Specify the {@link FaultMessageResolver} to use.
* @param resolver the resolver.
* @return the spec.
*/
public MarshallingWsOutboundGatewayNoTemplateSpec faultMessageResolver(FaultMessageResolver resolver) {
this.faultMessageResolver = resolver;
return this;
}
/**
* Specify the {@link WebServiceMessageSender}s to use.
* @param senders the senders.
* @return the spec.
*/
public MarshallingWsOutboundGatewayNoTemplateSpec messageSenders(WebServiceMessageSender... senders) {
this.messageSenders = Arrays.copyOf(senders, senders.length);
return this;
}
/**
* Specify the {@link ClientInterceptor}s to use.
* @param interceptors the interceptors.
* @return the spec.
*/
public MarshallingWsOutboundGatewayNoTemplateSpec interceptors(ClientInterceptor... interceptors) {
this.gatewayInterceptors = Arrays.copyOf(interceptors, interceptors.length);
return this;
}
@Override
protected MarshallingWebServiceOutboundGateway create() {
if (this.destinationProvider != null) {
return new MarshallingWebServiceOutboundGateway(this.destinationProvider, this.gatewayMarshaller,
this.gatewayUnmarshaller, this.webServiceMessageFactory);
}
else {
return new MarshallingWebServiceOutboundGateway(this.uri, this.gatewayMarshaller,
this.gatewayUnmarshaller, this.webServiceMessageFactory);
}
}
@Override
protected MarshallingWebServiceOutboundGateway assemble(MarshallingWebServiceOutboundGateway gateway) {
MarshallingWebServiceOutboundGateway assembled = super.assemble(gateway);
assembled.setFaultMessageResolver(this.faultMessageResolver);
assembled.setMessageSenders(this.messageSenders);
assembled.setInterceptors(this.gatewayInterceptors);
return assembled;
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://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.ws.dsl;
import org.springframework.integration.ws.SimpleWebServiceInboundGateway;
/**
* The spec for a {@link SimpleWebServiceInboundGateway}.
*
* @author Gary Russell
* @since 5.3
*
*/
public class SimpleWsInboundGatewaySpec extends BaseWsInboundGatewaySpec<SimpleWsInboundGatewaySpec,
SimpleWebServiceInboundGateway> {
protected boolean extractPayload = true; // NOSONAR
/**
* Specify true to extract the payloadSource from the request or use
* the entire request as the payload; default true.
* @param extract true to extract.
* @return the spec.
*/
public SimpleWsInboundGatewaySpec extractPayload(boolean extract) {
this.extractPayload = extract;
return this;
}
@Override
protected SimpleWebServiceInboundGateway create() {
SimpleWebServiceInboundGateway gateway = new SimpleWebServiceInboundGateway();
gateway.setExtractPayload(this.extractPayload);
return gateway;
}
}

View File

@@ -0,0 +1,193 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://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.ws.dsl;
import java.util.Arrays;
import org.springframework.integration.ws.MarshallingWebServiceOutboundGateway;
import org.springframework.integration.ws.SimpleWebServiceOutboundGateway;
import org.springframework.ws.WebServiceMessage;
import org.springframework.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.SourceExtractor;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* The spec for a {@link SimpleWebServiceOutboundGateway}.
*
* @author Gary Russell
* @since 5.3
*
*/
public class SimpleWsOutboundGatewaySpec extends BaseWsOutboundGatewaySpec<
SimpleWsOutboundGatewaySpec, SimpleWebServiceOutboundGateway> {
protected SourceExtractor<?> sourceExtractor; // NOSONAR
protected SimpleWsOutboundGatewaySpec(WebServiceTemplate template) {
this.template = template;
}
/**
* Configure a {@link SourceExtractor} to use.
* @param extractor the extractor.
* @return the spec.
*/
public SimpleWsOutboundGatewaySpec sourceExtractor(SourceExtractor<?> extractor) {
this.sourceExtractor = extractor;
return this;
}
/**
* Specify a flag to return the whole {@link WebServiceMessage} or build the
* {@code payload} based on {@link WebServiceMessage}
* and populated headers according {@code headerMapper} configuration.
* Defaults to extract payload.
* @param extract build payload or return a whole {@link WebServiceMessage}
* @return the spec.
*/
public SimpleWsOutboundGatewaySpec extractPayload(boolean extract) {
this.extractPayload = extract;
return this;
}
@Override
protected SimpleWebServiceOutboundGateway assemble(SimpleWebServiceOutboundGateway gateway) {
SimpleWebServiceOutboundGateway assembled = super.assemble(gateway);
assembled.setExtractPayload(this.extractPayload);
return assembled;
}
@Override
protected SimpleWebServiceOutboundGateway create() {
SimpleWebServiceOutboundGateway gateway;
if (this.destinationProvider != null) {
gateway = new SimpleWebServiceOutboundGateway(this.destinationProvider, this.sourceExtractor,
this.webServiceMessageFactory);
}
else {
gateway = new SimpleWebServiceOutboundGateway(this.uri, this.sourceExtractor,
this.webServiceMessageFactory);
}
gateway.setWebServiceTemplate(this.template);
return gateway;
}
/**
* Spec for a {@link MarshallingWebServiceOutboundGateway} where an external
* {@link WebServiceTemplate} is not provided.
*
*/
public static class SimpleWsOutboundGatewayNoTemplateSpec extends BaseWsOutboundGatewaySpec<
SimpleWsOutboundGatewayNoTemplateSpec, SimpleWebServiceOutboundGateway> {
protected SourceExtractor<?> sourceExtractor; // NOSONAR
private boolean extractPayload;
/**
* Configure a {@link SourceExtractor} to use.
* @param extractor the extractor.
* @return the spec.
*/
public SimpleWsOutboundGatewayNoTemplateSpec sourceExtractor(SourceExtractor<?> extractor) {
this.sourceExtractor = extractor;
return this;
}
/**
* Specify the {@link WebServiceMessageFactory} to use.
* @param messageFactory the message factory.
* @return the spec.
*/
public SimpleWsOutboundGatewayNoTemplateSpec messageFactory(WebServiceMessageFactory messageFactory) {
this.webServiceMessageFactory = messageFactory;
return this;
}
/**
* Specify the {@link FaultMessageResolver} to use.
* @param resolver the resolver.
* @return the spec.
*/
public SimpleWsOutboundGatewayNoTemplateSpec faultMessageResolver(FaultMessageResolver resolver) {
this.faultMessageResolver = resolver;
return this;
}
/**
* Specify the {@link WebServiceMessageSender}s to use.
* @param senders the senders.
* @return the spec.
*/
public SimpleWsOutboundGatewayNoTemplateSpec messageSenders(WebServiceMessageSender... senders) {
this.messageSenders = Arrays.copyOf(senders, senders.length);
return this;
}
/**
* Specify the {@link ClientInterceptor}s to use.
* @param interceptors the interceptors.
* @return the spec.
*/
public SimpleWsOutboundGatewayNoTemplateSpec interceptors(ClientInterceptor... interceptors) {
this.gatewayInterceptors = Arrays.copyOf(interceptors, interceptors.length);
return this;
}
/**
* Specify a flag to return the whole {@link WebServiceMessage} or build the
* {@code payload} based on {@link WebServiceMessage}
* and populated headers according {@code headerMapper} configuration.
* Defaults to extract payload.
* @param extract build payload or return a whole {@link WebServiceMessage}
* @return the spec.
*/
public SimpleWsOutboundGatewayNoTemplateSpec extractPayload(boolean extract) {
this.extractPayload = extract;
return this;
}
@Override
protected SimpleWebServiceOutboundGateway create() {
if (this.destinationProvider != null) {
return new SimpleWebServiceOutboundGateway(this.destinationProvider, this.sourceExtractor,
this.webServiceMessageFactory);
}
else {
return new SimpleWebServiceOutboundGateway(this.uri, this.sourceExtractor,
this.webServiceMessageFactory);
}
}
@Override
protected SimpleWebServiceOutboundGateway assemble(SimpleWebServiceOutboundGateway gateway) {
SimpleWebServiceOutboundGateway assembled = super.assemble(gateway);
assembled.setFaultMessageResolver(this.faultMessageResolver);
assembled.setMessageSenders(this.messageSenders);
assembled.setInterceptors(this.gatewayInterceptors);
assembled.setExtractPayload(this.extractPayload);
return assembled;
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://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.ws.dsl;
import org.springframework.integration.ws.dsl.MarshallingWsOutboundGatewaySpec.MarshallingWsOutboundGatewayNoTemplateSpec;
import org.springframework.integration.ws.dsl.SimpleWsOutboundGatewaySpec.SimpleWsOutboundGatewayNoTemplateSpec;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.ws.client.core.WebServiceTemplate;
/**
* Factory class for web service components.
*
* @author Gary Russell
* @since 5.3
*
*/
public final class Ws {
/**
* Create an instance.
* @return the spec.
*/
public static MarshallingWsInboundGatewaySpec marshallingInboundGateway() {
return new MarshallingWsInboundGatewaySpec();
}
/**
* Create an instance with the provided {@link Marshaller} (which must also implement
* {@link Unmarshaller}).
* @param marshaller the marshaller.
* @return the spec.
*/
public static MarshallingWsInboundGatewaySpec marshallingInboundGateway(Marshaller marshaller) {
MarshallingWsInboundGatewaySpec spec = new MarshallingWsInboundGatewaySpec();
spec.marshaller(marshaller);
return spec;
}
/**
* Create an instance.
* @return the spec.
*/
public static SimpleWsInboundGatewaySpec simpleInboundGateway() {
return new SimpleWsInboundGatewaySpec();
}
/**
* Create an instance with a default {@link WebServiceTemplate}.
* @return the spec.
*/
public static MarshallingWsOutboundGatewayNoTemplateSpec marshallingOutboundGateway() {
return new MarshallingWsOutboundGatewayNoTemplateSpec();
}
/**
* Create an instance with the provided {@link WebServiceTemplate}.
* @param template the template.
* @return the spec.
*/
public static MarshallingWsOutboundGatewaySpec marshallingOutboundGateway(WebServiceTemplate template) {
return new MarshallingWsOutboundGatewaySpec(template);
}
/**
* Create an instance.
* @return the spec.
*/
public static SimpleWsOutboundGatewayNoTemplateSpec simpleOutboundGateway() {
return new SimpleWsOutboundGatewayNoTemplateSpec();
}
/**
* Create an instance with the provided {@link WebServiceTemplate}.
* @param template the template.
* @return the spec.
*/
public static SimpleWsOutboundGatewaySpec simpleOutboundGateway(WebServiceTemplate template) {
return new SimpleWsOutboundGatewaySpec(template);
}
private Ws() {
}
}

View File

@@ -0,0 +1,4 @@
/**
* Contains classes for DSL support.
*/
package org.springframework.integration.ws.dsl;

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.
@@ -131,7 +131,7 @@ public class SimpleWebServiceOutboundGatewayTests {
SimpleWebServiceOutboundGateway gateway = new SimpleWebServiceOutboundGateway("http://testInt3022");
gateway.setRequiresReply(true);
WebServiceMessageSender messageSender = createMockMessageSender(responseEmptyBodySoapMessage);
gateway.setMessageSender(messageSender);
gateway.setMessageSenders(messageSender);
gateway.handleMessage(new GenericMessage<String>("<test>foo</test>"));
}

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.
@@ -261,7 +261,7 @@ public class WebServiceOutboundGatewayWithHeaderMapperTests {
return wsMessage;
}).when(wsConnection).receive(Mockito.any(WebServiceMessageFactory.class));
gateway.setMessageSender(messageSender);
gateway.setMessageSenders(messageSender);
MessageChannel inputChannel = context.getBean(channelName, MessageChannel.class);
Message<?> message =

View File

@@ -0,0 +1,215 @@
/*
* Copyright 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.
* You may obtain a copy of the License at
*
* https://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.ws.dsl;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.expression.Expression;
import org.springframework.expression.common.LiteralExpression;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.ws.MarshallingWebServiceInboundGateway;
import org.springframework.integration.ws.MarshallingWebServiceOutboundGateway;
import org.springframework.integration.ws.SimpleWebServiceInboundGateway;
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.ws.WebServiceMessageFactory;
import org.springframework.ws.client.core.FaultMessageResolver;
import org.springframework.ws.client.core.SourceExtractor;
import org.springframework.ws.client.core.WebServiceMessageCallback;
import org.springframework.ws.client.core.WebServiceTemplate;
import org.springframework.ws.client.support.destination.DestinationProvider;
import org.springframework.ws.client.support.interceptor.ClientInterceptor;
import org.springframework.ws.transport.WebServiceMessageSender;
/**
* @author Gary Russell
* @since 5.3
*
*/
public class WsDslTests {
@Test
void marshallingInbound() {
Marshaller marshaller = mock(Marshaller.class);
Unmarshaller unmarshaller = mock(Unmarshaller.class);
MarshallingWebServiceInboundGateway gateway = Ws.marshallingInboundGateway(marshaller)
.unmarshaller(unmarshaller)
.get();
assertThat(TestUtils.getPropertyValue(gateway, "marshaller")).isSameAs(marshaller);
assertThat(TestUtils.getPropertyValue(gateway, "unmarshaller")).isSameAs(unmarshaller);
marshaller = mock(Both.class);
gateway = Ws.marshallingInboundGateway(marshaller).get();
assertThat(TestUtils.getPropertyValue(gateway, "marshaller")).isSameAs(marshaller);
assertThat(TestUtils.getPropertyValue(gateway, "unmarshaller")).isSameAs(marshaller);
}
@Test
void simpleInbound() {
SimpleWebServiceInboundGateway gateway = Ws.simpleInboundGateway()
.extractPayload(false)
.get();
assertThat(TestUtils.getPropertyValue(gateway, "extractPayload", Boolean.class)).isFalse();
}
@Test
void marshallingOutbound() {
DestinationProvider destinationProvider = mock(DestinationProvider.class);
Marshaller marshaller = mock(Marshaller.class);
Unmarshaller unmarshaller = mock(Unmarshaller.class);
WebServiceMessageFactory messageFactory = mock(WebServiceMessageFactory.class);
FaultMessageResolver faultMessageResolver = mock(FaultMessageResolver.class);
SoapHeaderMapper headerMapper = mock(SoapHeaderMapper.class);
ClientInterceptor interceptor = mock(ClientInterceptor.class);
WebServiceMessageSender messageSender = mock(WebServiceMessageSender.class);
WebServiceMessageCallback requestCallback = msg -> { };
Map<String, Expression> uriVariableExpressions = new HashMap<>();
uriVariableExpressions.put("foo", new LiteralExpression("bar"));
MarshallingWebServiceOutboundGateway gateway =
Ws.marshallingOutboundGateway()
.destinationProvider(destinationProvider)
.marshaller(marshaller)
.unmarshaller(unmarshaller)
.messageFactory(messageFactory)
.encodeUri(true)
.faultMessageResolver(faultMessageResolver)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.interceptors(interceptor)
.messageSenders(messageSender)
.requestCallback(requestCallback)
.uriVariableExpressions(uriVariableExpressions)
.get();
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.marshaller")).isSameAs(marshaller);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.unmarshaller")).isSameAs(unmarshaller);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.messageFactory")).isSameAs(messageFactory);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.faultMessageResolver"))
.isSameAs(faultMessageResolver);
assertThat(TestUtils.getPropertyValue(gateway, "headerMapper")).isSameAs(headerMapper);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.interceptors", ClientInterceptor[].class)[0])
.isSameAs(interceptor);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.messageSenders",
WebServiceMessageSender[].class)[0])
.isSameAs(messageSender);
assertThat(TestUtils.getPropertyValue(gateway, "requestCallback")).isSameAs(requestCallback);
assertThat(TestUtils.getPropertyValue(gateway, "uriVariableExpressions")).isEqualTo(uriVariableExpressions);
}
@Test
void simpleOutbound() {
DestinationProvider destinationProvider = mock(DestinationProvider.class);
WebServiceMessageFactory messageFactory = mock(WebServiceMessageFactory.class);
FaultMessageResolver faultMessageResolver = mock(FaultMessageResolver.class);
SoapHeaderMapper headerMapper = mock(SoapHeaderMapper.class);
ClientInterceptor interceptor = mock(ClientInterceptor.class);
WebServiceMessageSender messageSender = mock(WebServiceMessageSender.class);
WebServiceMessageCallback requestCallback = msg -> { };
Map<String, Expression> uriVariableExpressions = new HashMap<>();
uriVariableExpressions.put("foo", new LiteralExpression("bar"));
SourceExtractor<?> sourceExtractor = mock(SourceExtractor.class);
SimpleWebServiceOutboundGateway gateway =
Ws.simpleOutboundGateway()
.destinationProvider(destinationProvider)
.sourceExtractor(sourceExtractor)
.messageFactory(messageFactory)
.encodeUri(true)
.faultMessageResolver(faultMessageResolver)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.interceptors(interceptor)
.messageSenders(messageSender)
.requestCallback(requestCallback)
.uriVariableExpressions(uriVariableExpressions)
.extractPayload(false)
.get();
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.messageFactory")).isSameAs(messageFactory);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.faultMessageResolver"))
.isSameAs(faultMessageResolver);
assertThat(TestUtils.getPropertyValue(gateway, "headerMapper")).isSameAs(headerMapper);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.interceptors", ClientInterceptor[].class)[0])
.isSameAs(interceptor);
assertThat(TestUtils.getPropertyValue(gateway, "webServiceTemplate.messageSenders",
WebServiceMessageSender[].class)[0])
.isSameAs(messageSender);
assertThat(TestUtils.getPropertyValue(gateway, "requestCallback")).isSameAs(requestCallback);
assertThat(TestUtils.getPropertyValue(gateway, "uriVariableExpressions")).isEqualTo(uriVariableExpressions);
assertThat(TestUtils.getPropertyValue(gateway, "extractPayload", Boolean.class)).isFalse();
}
@Test
void marshallingOutboundTemplate() {
SoapHeaderMapper headerMapper = mock(SoapHeaderMapper.class);
WebServiceMessageCallback requestCallback = msg -> { };
Map<String, Expression> uriVariableExpressions = new HashMap<>();
uriVariableExpressions.put("foo", new LiteralExpression("bar"));
WebServiceTemplate template = mock(WebServiceTemplate.class);
String uri = "foo";
MarshallingWebServiceOutboundGateway gateway =
Ws.marshallingOutboundGateway(template)
.uri(uri)
.encodeUri(true)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.requestCallback(requestCallback)
.uriVariableExpressions(uriVariableExpressions)
.get();
assertThat(TestUtils.getPropertyValue(gateway, "uri")).isSameAs(uri);
assertThat(TestUtils.getPropertyValue(gateway, "headerMapper")).isSameAs(headerMapper);
assertThat(TestUtils.getPropertyValue(gateway, "requestCallback")).isSameAs(requestCallback);
assertThat(TestUtils.getPropertyValue(gateway, "uriVariableExpressions")).isEqualTo(uriVariableExpressions);
}
@Test
void simpleOutboundTemplate() {
SoapHeaderMapper headerMapper = mock(SoapHeaderMapper.class);
WebServiceMessageCallback requestCallback = msg -> { };
Map<String, Expression> uriVariableExpressions = new HashMap<>();
uriVariableExpressions.put("foo", new LiteralExpression("bar"));
SourceExtractor<?> sourceExtractor = mock(SourceExtractor.class);
WebServiceTemplate template = mock(WebServiceTemplate.class);
String uri = "foo";
SimpleWebServiceOutboundGateway gateway =
Ws.simpleOutboundGateway(template)
.uri(uri)
.sourceExtractor(sourceExtractor)
.encodeUri(true)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.requestCallback(requestCallback)
.uriVariableExpressions(uriVariableExpressions)
.extractPayload(false)
.get();
assertThat(TestUtils.getPropertyValue(gateway, "headerMapper")).isSameAs(headerMapper);
assertThat(TestUtils.getPropertyValue(gateway, "requestCallback")).isSameAs(requestCallback);
assertThat(TestUtils.getPropertyValue(gateway, "uriVariableExpressions")).isEqualTo(uriVariableExpressions);
assertThat(TestUtils.getPropertyValue(gateway, "extractPayload", Boolean.class)).isFalse();
}
interface Both extends Marshaller, Unmarshaller {
}
}

View File

@@ -68,3 +68,9 @@ 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.
[[x5.3-ws]]
=== Web Services Changes
Java DSL support has been added for Web Service components.
See <<./ws.adoc#ws,Web Services Support>> for more information.

View File

@@ -169,6 +169,113 @@ Doing so might be useful, for example, when a custom transformer works against t
Starting with version 5.0, the `web-service-template` reference attribute lets you inject a `WebServiceTemplate` with any possible custom properties.
[[webservices-dsl]]
=== Web Service Java DSL Support
The equivalent configuration for the gateways shown in <<webservices-namespace>> are shown in the following snippets:
====
[source, java]
----
@Bean
IntegrationFlow inbound() {
return IntegrationFlows.from(Ws.simpleInboundGateway()
.id("simpleGateway"))
...
.get();
}
----
====
====
[source, java]
----
@Bean
IntegrationFlow outboundMarshalled() {
return f -> f.handle(Ws.marshallingOutboundGateway()
.id("marshallingGateway")
.marshaller(someMarshaller())
.unmarshaller(someUnmarshalller()))
...
}
----
====
====
[source, java]
----
@Bean
IntegrationFlow inboundMarshalled() {
return IntegrationFlows.from(Ws.marshallingInboundGateway()
.marshaller(someMarshaller())
.unmarshaller(someUnmarshalller())
.id("marshallingGateway"))
...
.get();
}
----
====
Other properties can be set on the endpoint specs in a fluent manner (with the properties depending on whether or not an external `WebServiceTemplate` has been provided for outbound gateways).
Examples:
====
[source, java]
----
.from(Ws.simpleInboundGateway()
.extractPayload(false))
----
====
====
[source, java]
----
.handle(Ws.simpleOutboundGateway(template)
.uri(uri)
.sourceExtractor(sourceExtractor)
.encodeUri(true)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.requestCallback(requestCallback)
.uriVariableExpressions(uriVariableExpressions)
.extractPayload(false))
)
----
====
====
[source, java]
----
.handle(Ws.marshallingOutboundGateway()
.destinationProvider(destinationProvider)
.marshaller(marshaller)
.unmarshaller(unmarshaller)
.messageFactory(messageFactory)
.encodeUri(true)
.faultMessageResolver(faultMessageResolver)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.interceptors(interceptor)
.messageSenders(messageSender)
.requestCallback(requestCallback)
.uriVariableExpressions(uriVariableExpressions))
----
====
====
[source, java]
----
.handle(Ws.marshallingOutboundGateway(template)
.uri(uri)
.encodeUri(true)
.headerMapper(headerMapper)
.ignoreEmptyResponses(true)
.requestCallback(requestCallback)
.uriVariableExpressions(uriVariableExpressions))
)
----
====
[[outbound-uri]]
=== Outbound URI Configuration