Update web services support to use ClientHttpRequestFactoryBuilder

Add a new `WebServiceMessageSenderFactory` factory interface to replace
`HttpWebServiceMessageSenderBuilder`. The factory provides a general
purpose way of creating `WebServiceMessageSender` instances, but most
typically will be `ClientHttpRequestMessageSender` created from a
`ClientHttpRequestFactoryBuilder`.

A new `httpMessageSenderFactory` method has been added to the
`WebServiceTemplateBuilder` class. This allows any sender to be
plugged into the template.

Closes gh-42886
This commit is contained in:
Phillip Webb
2024-10-24 00:04:57 -07:00
parent 022f3cb019
commit 6356e904fc
11 changed files with 342 additions and 81 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2021 the original author or authors.
* Copyright 2012-2024 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.
@@ -18,7 +18,8 @@ package org.springframework.boot.docs.io.webservices.template;
import java.time.Duration;
import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
import org.springframework.boot.webservices.client.WebServiceMessageSenderFactory;
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -30,13 +31,11 @@ public class MyWebServiceTemplateConfiguration {
@Bean
public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) {
// @formatter:off
WebServiceMessageSender sender = new HttpWebServiceMessageSenderBuilder()
.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2))
.build();
ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.defaults()
.withConnectTimeout(Duration.ofSeconds(2))
.withReadTimeout(Duration.ofSeconds(2));
WebServiceMessageSender sender = WebServiceMessageSenderFactory.http(settings).getWebServiceMessageSender();
return builder.messageSenders(sender).build();
// @formatter:on
}
}
@@ -16,7 +16,8 @@
package org.springframework.boot.docs.io.webservices.template
import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings
import org.springframework.boot.webservices.client.WebServiceMessageSenderFactory
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@@ -28,11 +29,11 @@ class MyWebServiceTemplateConfiguration {
@Bean
fun webServiceTemplate(builder: WebServiceTemplateBuilder): WebServiceTemplate {
val sender = HttpWebServiceMessageSenderBuilder()
.setConnectTimeout(Duration.ofSeconds(5))
.setReadTimeout(Duration.ofSeconds(2))
.build()
return builder.messageSenders(sender).build()
val settings = ClientHttpRequestFactorySettings.defaults()
.withConnectTimeout(Duration.ofSeconds(2))
.withReadTimeout(Duration.ofSeconds(2));
val sender = WebServiceMessageSenderFactory.http(settings).getWebServiceMessageSender();
return builder.messageSenders(sender).build();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -20,13 +20,13 @@ import java.time.Duration;
import java.util.function.Function;
import java.util.function.Supplier;
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
import org.springframework.boot.http.client.JdkClientHttpRequestFactoryBuilder;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.web.client.ClientHttpRequestFactories;
import org.springframework.boot.web.client.ClientHttpRequestFactorySettings;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.util.Assert;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;
/**
* {@link WebServiceMessageSender} builder that can detect a suitable HTTP library based
@@ -34,16 +34,15 @@ import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;
*
* @author Stephane Nicoll
* @since 2.1.0
* @deprecated since 3.4.0 in favor of
* {@link WebServiceMessageSenderFactory#http(ClientHttpRequestFactorySettings)}
*/
@Deprecated(since = "3.4.0", forRemoval = true)
public class HttpWebServiceMessageSenderBuilder {
private Duration connectTimeout;
private ClientHttpRequestFactoryBuilder<?> requestFactoryBuilder;
private Duration readTimeout;
private SslBundle sslBundle;
private Function<ClientHttpRequestFactorySettings, ClientHttpRequestFactory> requestFactory;
private ClientHttpRequestFactorySettings requestFactorySettings = ClientHttpRequestFactorySettings.defaults();
/**
* Set the connection timeout.
@@ -51,7 +50,7 @@ public class HttpWebServiceMessageSenderBuilder {
* @return a new builder instance
*/
public HttpWebServiceMessageSenderBuilder setConnectTimeout(Duration connectTimeout) {
this.connectTimeout = connectTimeout;
this.requestFactorySettings = this.requestFactorySettings.withConnectTimeout(connectTimeout);
return this;
}
@@ -61,7 +60,7 @@ public class HttpWebServiceMessageSenderBuilder {
* @return a new builder instance
*/
public HttpWebServiceMessageSenderBuilder setReadTimeout(Duration readTimeout) {
this.readTimeout = readTimeout;
this.requestFactorySettings = this.requestFactorySettings.withReadTimeout(readTimeout);
return this;
}
@@ -71,7 +70,7 @@ public class HttpWebServiceMessageSenderBuilder {
* @return a new builder instance
*/
public HttpWebServiceMessageSenderBuilder sslBundle(SslBundle sslBundle) {
this.sslBundle = sslBundle;
this.requestFactorySettings = this.requestFactorySettings.withSslBundle(sslBundle);
return this;
}
@@ -84,7 +83,7 @@ public class HttpWebServiceMessageSenderBuilder {
public HttpWebServiceMessageSenderBuilder requestFactory(
Supplier<ClientHttpRequestFactory> requestFactorySupplier) {
Assert.notNull(requestFactorySupplier, "RequestFactorySupplier must not be null");
this.requestFactory = (settings) -> ClientHttpRequestFactories.get(requestFactorySupplier, settings);
this.requestFactoryBuilder = ClientHttpRequestFactoryBuilder.of(requestFactorySupplier);
return this;
}
@@ -99,7 +98,21 @@ public class HttpWebServiceMessageSenderBuilder {
public HttpWebServiceMessageSenderBuilder requestFactory(
Function<ClientHttpRequestFactorySettings, ClientHttpRequestFactory> requestFactoryFunction) {
Assert.notNull(requestFactoryFunction, "RequestFactoryFunction must not be null");
this.requestFactory = requestFactoryFunction;
this.requestFactoryBuilder = requestFactoryFunction::apply;
return this;
}
/**
* Set the {@link ClientHttpRequestFactoryBuilder} to use when creating the HTTP-based
* {@link WebServiceMessageSender}.
* @param requestFactoryBuilder the {@link ClientHttpRequestFactoryBuilder} to use
* @return this builder instance
* @since 3.4.0
*/
public HttpWebServiceMessageSenderBuilder requestFactoryBuilder(
ClientHttpRequestFactoryBuilder<?> requestFactoryBuilder) {
Assert.notNull(requestFactoryBuilder, "ClientHttpRequestFactoryBuilder must not be null");
this.requestFactoryBuilder = requestFactoryBuilder;
return this;
}
@@ -108,14 +121,21 @@ public class HttpWebServiceMessageSenderBuilder {
* @return the {@link WebServiceMessageSender} instance
*/
public WebServiceMessageSender build() {
return new ClientHttpRequestMessageSender(getRequestFactory());
ClientHttpRequestFactoryBuilder<?> requestFactoryBuilder = getOrDetectRequestFactoryBuilder();
return WebServiceMessageSenderFactory.http(requestFactoryBuilder, this.requestFactorySettings)
.getWebServiceMessageSender();
}
private ClientHttpRequestFactory getRequestFactory() {
ClientHttpRequestFactorySettings settings = new ClientHttpRequestFactorySettings(this.connectTimeout,
this.readTimeout, this.sslBundle);
return (this.requestFactory != null) ? this.requestFactory.apply(settings)
: ClientHttpRequestFactories.get(settings);
private ClientHttpRequestFactoryBuilder<?> getOrDetectRequestFactoryBuilder() {
if (this.requestFactoryBuilder != null) {
return this.requestFactoryBuilder;
}
ClientHttpRequestFactoryBuilder<?> builder = ClientHttpRequestFactoryBuilder.detect();
if (builder instanceof JdkClientHttpRequestFactoryBuilder) {
// Same logic as earlier versions which did not support JDK client factories
return ClientHttpRequestFactoryBuilder.simple();
}
return builder;
}
}
@@ -0,0 +1,74 @@
/*
* Copyright 2012-2024 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.boot.webservices.client;
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.util.Assert;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;
/**
* Factory that can be used to create a {@link WebServiceMessageSender}.
*
* @author Phillip Webb
* @since 3.4.0
*/
@FunctionalInterface
public interface WebServiceMessageSenderFactory {
/**
* Return a new {@link WebServiceMessageSender} instance.
* @return the web service message sender
*/
WebServiceMessageSender getWebServiceMessageSender();
/**
* Returns a factory that will create a {@link ClientHttpRequestMessageSender} backed
* by a detected {@link ClientHttpRequestFactory}.
* @return a new {@link WebServiceMessageSenderFactory}
*/
static WebServiceMessageSenderFactory http() {
return http(ClientHttpRequestFactoryBuilder.detect(), null);
}
/**
* Returns a factory that will create a {@link ClientHttpRequestMessageSender} backed
* by a detected {@link ClientHttpRequestFactory}.
* @param requestFactorySettings the setting to apply
* @return a new {@link WebServiceMessageSenderFactory}
*/
static WebServiceMessageSenderFactory http(ClientHttpRequestFactorySettings requestFactorySettings) {
return http(ClientHttpRequestFactoryBuilder.detect(), requestFactorySettings);
}
/**
* Returns a factory that will create a {@link ClientHttpRequestMessageSender} backed
* by a {@link ClientHttpRequestFactory} created from the given
* {@link ClientHttpRequestFactoryBuilder}.
* @param requestFactoryBuilder the request factory builder to use
* @param requestFactorySettings the settings to apply
* @return a new {@link WebServiceMessageSenderFactory}
*/
static WebServiceMessageSenderFactory http(ClientHttpRequestFactoryBuilder<?> requestFactoryBuilder,
ClientHttpRequestFactorySettings requestFactorySettings) {
Assert.notNull(requestFactoryBuilder, "'requestFactoryBuilder' must not be null");
return () -> new ClientHttpRequestMessageSender(requestFactoryBuilder.build(requestFactorySettings));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -56,6 +56,8 @@ import org.springframework.ws.transport.WebServiceMessageSender;
*/
public class WebServiceTemplateBuilder {
private final WebServiceMessageSenderFactory httpMessageSenderFactory;
private final boolean detectHttpMessageSender;
private final Set<ClientInterceptor> interceptors;
@@ -77,6 +79,7 @@ public class WebServiceTemplateBuilder {
private final WebServiceMessageFactory messageFactory;
public WebServiceTemplateBuilder(WebServiceTemplateCustomizer... customizers) {
this.httpMessageSenderFactory = null;
this.detectHttpMessageSender = true;
this.interceptors = null;
this.internalCustomizers = null;
@@ -89,11 +92,13 @@ public class WebServiceTemplateBuilder {
this.messageFactory = null;
}
private WebServiceTemplateBuilder(boolean detectHttpMessageSender, Set<ClientInterceptor> interceptors,
private WebServiceTemplateBuilder(WebServiceMessageSenderFactory messageSenderFactory,
boolean detectHttpMessageSender, Set<ClientInterceptor> interceptors,
Set<WebServiceTemplateCustomizer> internalCustomizers, Set<WebServiceTemplateCustomizer> customizers,
WebServiceMessageSenders messageSenders, Marshaller marshaller, Unmarshaller unmarshaller,
DestinationProvider destinationProvider, Class<? extends TransformerFactory> transformerFactoryClass,
WebServiceMessageFactory messageFactory) {
this.httpMessageSenderFactory = messageSenderFactory;
this.detectHttpMessageSender = detectHttpMessageSender;
this.interceptors = interceptors;
this.internalCustomizers = internalCustomizers;
@@ -106,18 +111,33 @@ public class WebServiceTemplateBuilder {
this.messageFactory = messageFactory;
}
/**
* Set the {@link WebServiceMessageSenderFactory} that should be used to send HTTP
* messages.
* @param messageSenderFactory the {@link WebServiceMessageSenderFactory} to use
* @return a new builder instance
* @since 3.4.0
* @see HttpWebServiceMessageSenderBuilder
*/
public WebServiceTemplateBuilder httpMessageSenderFactory(WebServiceMessageSenderFactory messageSenderFactory) {
Assert.notNull(this.messageSenders, "HttpWebServiceMessageSenderBuilder must not be null");
return new WebServiceTemplateBuilder(messageSenderFactory, this.detectHttpMessageSender, this.interceptors,
this.internalCustomizers, this.customizers, this.messageSenders, this.marshaller, this.unmarshaller,
this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
}
/**
* Set if a suitable HTTP-based {@link WebServiceMessageSender} should be detected
* based on the classpath. Default is {@code true}.
* based on the classpath when one has not been specified. Default is {@code true}.
* @param detectHttpMessageSender if an HTTP-based {@link WebServiceMessageSender}
* should be detected
* @return a new builder instance
* @see HttpWebServiceMessageSenderBuilder
*/
public WebServiceTemplateBuilder detectHttpMessageSender(boolean detectHttpMessageSender) {
return new WebServiceTemplateBuilder(detectHttpMessageSender, this.interceptors, this.internalCustomizers,
this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
this.transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, detectHttpMessageSender, this.interceptors,
this.internalCustomizers, this.customizers, this.messageSenders, this.marshaller, this.unmarshaller,
this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
}
/**
@@ -149,9 +169,10 @@ public class WebServiceTemplateBuilder {
*/
public WebServiceTemplateBuilder messageSenders(Collection<? extends WebServiceMessageSender> messageSenders) {
Assert.notNull(messageSenders, "MessageSenders must not be null");
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
this.customizers, this.messageSenders.set(messageSenders), this.marshaller, this.unmarshaller,
this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers, this.customizers, this.messageSenders.set(messageSenders),
this.marshaller, this.unmarshaller, this.destinationProvider, this.transformerFactoryClass,
this.messageFactory);
}
/**
@@ -176,9 +197,10 @@ public class WebServiceTemplateBuilder {
public WebServiceTemplateBuilder additionalMessageSenders(
Collection<? extends WebServiceMessageSender> messageSenders) {
Assert.notNull(messageSenders, "MessageSenders must not be null");
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
this.customizers, this.messageSenders.add(messageSenders), this.marshaller, this.unmarshaller,
this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers, this.customizers, this.messageSenders.add(messageSenders),
this.marshaller, this.unmarshaller, this.destinationProvider, this.transformerFactoryClass,
this.messageFactory);
}
/**
@@ -204,7 +226,7 @@ public class WebServiceTemplateBuilder {
*/
public WebServiceTemplateBuilder interceptors(Collection<? extends ClientInterceptor> interceptors) {
Assert.notNull(interceptors, "Interceptors must not be null");
return new WebServiceTemplateBuilder(this.detectHttpMessageSender,
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
append(Collections.<ClientInterceptor>emptySet(), interceptors), this.internalCustomizers,
this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
this.transformerFactoryClass, this.messageFactory);
@@ -231,9 +253,10 @@ public class WebServiceTemplateBuilder {
*/
public WebServiceTemplateBuilder additionalInterceptors(Collection<? extends ClientInterceptor> interceptors) {
Assert.notNull(interceptors, "Interceptors must not be null");
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, append(this.interceptors, interceptors),
this.internalCustomizers, this.customizers, this.messageSenders, this.marshaller, this.unmarshaller,
this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
append(this.interceptors, interceptors), this.internalCustomizers, this.customizers,
this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
this.transformerFactoryClass, this.messageFactory);
}
/**
@@ -261,7 +284,8 @@ public class WebServiceTemplateBuilder {
*/
public WebServiceTemplateBuilder customizers(Collection<? extends WebServiceTemplateCustomizer> customizers) {
Assert.notNull(customizers, "Customizers must not be null");
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers,
append(Collections.<WebServiceTemplateCustomizer>emptySet(), customizers), this.messageSenders,
this.marshaller, this.unmarshaller, this.destinationProvider, this.transformerFactoryClass,
this.messageFactory);
@@ -291,9 +315,10 @@ public class WebServiceTemplateBuilder {
public WebServiceTemplateBuilder additionalCustomizers(
Collection<? extends WebServiceTemplateCustomizer> customizers) {
Assert.notNull(customizers, "Customizers must not be null");
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
append(this.customizers, customizers), this.messageSenders, this.marshaller, this.unmarshaller,
this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers, append(this.customizers, customizers), this.messageSenders,
this.marshaller, this.unmarshaller, this.destinationProvider, this.transformerFactoryClass,
this.messageFactory);
}
/**
@@ -304,7 +329,8 @@ public class WebServiceTemplateBuilder {
* @see WebServiceTemplate#setCheckConnectionForFault(boolean)
*/
public WebServiceTemplateBuilder setCheckConnectionForFault(boolean checkConnectionForFault) {
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors,
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors,
append(this.internalCustomizers, new CheckConnectionFaultCustomizer(checkConnectionForFault)),
this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
this.transformerFactoryClass, this.messageFactory);
@@ -318,7 +344,8 @@ public class WebServiceTemplateBuilder {
* @see WebServiceTemplate#setCheckConnectionForError(boolean)
*/
public WebServiceTemplateBuilder setCheckConnectionForError(boolean checkConnectionForError) {
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors,
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors,
append(this.internalCustomizers, new CheckConnectionForErrorCustomizer(checkConnectionForError)),
this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
this.transformerFactoryClass, this.messageFactory);
@@ -332,9 +359,9 @@ public class WebServiceTemplateBuilder {
*/
public WebServiceTemplateBuilder setWebServiceMessageFactory(WebServiceMessageFactory messageFactory) {
Assert.notNull(messageFactory, "MessageFactory must not be null");
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
this.transformerFactoryClass, messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers, this.customizers, this.messageSenders, this.marshaller,
this.unmarshaller, this.destinationProvider, this.transformerFactoryClass, messageFactory);
}
/**
@@ -344,9 +371,9 @@ public class WebServiceTemplateBuilder {
* @see WebServiceTemplate#setUnmarshaller(Unmarshaller)
*/
public WebServiceTemplateBuilder setUnmarshaller(Unmarshaller unmarshaller) {
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
this.customizers, this.messageSenders, this.marshaller, unmarshaller, this.destinationProvider,
this.transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers, this.customizers, this.messageSenders, this.marshaller,
unmarshaller, this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
}
/**
@@ -356,9 +383,9 @@ public class WebServiceTemplateBuilder {
* @see WebServiceTemplate#setMarshaller(Marshaller)
*/
public WebServiceTemplateBuilder setMarshaller(Marshaller marshaller) {
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
this.customizers, this.messageSenders, marshaller, this.unmarshaller, this.destinationProvider,
this.transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers, this.customizers, this.messageSenders, marshaller,
this.unmarshaller, this.destinationProvider, this.transformerFactoryClass, this.messageFactory);
}
/**
@@ -368,7 +395,8 @@ public class WebServiceTemplateBuilder {
* @see WebServiceTemplate#setFaultMessageResolver(FaultMessageResolver)
*/
public WebServiceTemplateBuilder setFaultMessageResolver(FaultMessageResolver faultMessageResolver) {
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors,
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors,
append(this.internalCustomizers, new FaultMessageResolverCustomizer(faultMessageResolver)),
this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
this.transformerFactoryClass, this.messageFactory);
@@ -382,9 +410,9 @@ public class WebServiceTemplateBuilder {
*/
public WebServiceTemplateBuilder setTransformerFactoryClass(
Class<? extends TransformerFactory> transformerFactoryClass) {
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, this.destinationProvider,
transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers, this.customizers, this.messageSenders, this.marshaller,
this.unmarshaller, this.destinationProvider, transformerFactoryClass, this.messageFactory);
}
/**
@@ -411,9 +439,9 @@ public class WebServiceTemplateBuilder {
*/
public WebServiceTemplateBuilder setDestinationProvider(DestinationProvider destinationProvider) {
Assert.notNull(destinationProvider, "DestinationProvider must not be null");
return new WebServiceTemplateBuilder(this.detectHttpMessageSender, this.interceptors, this.internalCustomizers,
this.customizers, this.messageSenders, this.marshaller, this.unmarshaller, destinationProvider,
this.transformerFactoryClass, this.messageFactory);
return new WebServiceTemplateBuilder(this.httpMessageSenderFactory, this.detectHttpMessageSender,
this.interceptors, this.internalCustomizers, this.customizers, this.messageSenders, this.marshaller,
this.unmarshaller, destinationProvider, this.transformerFactoryClass, this.messageFactory);
}
/**
@@ -480,9 +508,12 @@ public class WebServiceTemplateBuilder {
}
private <T extends WebServiceTemplate> void configureMessageSenders(T webServiceTemplate) {
if (this.messageSenders.isOnlyAdditional() && this.detectHttpMessageSender) {
if (this.messageSenders.isOnlyAdditional()
&& (this.httpMessageSenderFactory != null || this.detectHttpMessageSender)) {
WebServiceMessageSenderFactory httpMessageSenderFactory = (this.httpMessageSenderFactory != null)
? this.httpMessageSenderFactory : WebServiceMessageSenderFactory.http();
Set<WebServiceMessageSender> merged = append(this.messageSenders.getMessageSenders(),
new HttpWebServiceMessageSenderBuilder().build());
httpMessageSenderFactory.getWebServiceMessageSender());
webServiceTemplate.setMessageSenders(merged.toArray(new WebServiceMessageSender[0]));
}
else if (!CollectionUtils.isEmpty(this.messageSenders.getMessageSenders())) {
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Stephane Nicoll
*/
@ClassPathExclusions("httpclient5-*.jar")
@SuppressWarnings("removal")
class HttpWebServiceMessageSenderBuilderJettyClientIntegrationTests {
private final HttpWebServiceMessageSenderBuilder builder = new HttpWebServiceMessageSenderBuilder();
@@ -38,6 +38,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Andy Wilkinson
*/
@ClassPathExclusions({ "httpclient5-*.jar", "jetty-client-*.jar" })
@SuppressWarnings("removal")
class HttpWebServiceMessageSenderBuilderReactorClientIntegrationTests {
private final HttpWebServiceMessageSenderBuilder builder = new HttpWebServiceMessageSenderBuilder();
@@ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* @author Stephane Nicoll
*/
@ClassPathExclusions({ "httpclient5-*.jar", "jetty-client-*.jar", "reactor-netty-http-*.jar" })
@SuppressWarnings("removal")
class HttpWebServiceMessageSenderBuilderSimpleIntegrationTests {
private final HttpWebServiceMessageSenderBuilder builder = new HttpWebServiceMessageSenderBuilder();
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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.
@@ -34,6 +34,7 @@ import static org.mockito.Mockito.mock;
*
* @author Stephane Nicoll
*/
@SuppressWarnings("removal")
class HttpWebServiceMessageSenderBuilderTests {
@Test
@@ -0,0 +1,120 @@
/*
* Copyright 2012-2024 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.boot.webservices.client;
import java.time.Duration;
import org.eclipse.jetty.client.HttpClient;
import org.junit.jupiter.api.Test;
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.http.client.JettyClientHttpRequestFactory;
import org.springframework.http.client.ReactorClientHttpRequestFactory;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.ws.transport.WebServiceMessageSender;
import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
/**
* Tests for {@link WebServiceMessageSenderFactory}.
*
* @author Phillip Webb
* @author Stephane Nicoll
* @author Andy Wilkinson
*/
class WebServiceMessageSenderFactoryTests {
@Test
void httpWhenDetectedHttpComponents() {
WebServiceMessageSender sender = WebServiceMessageSenderFactory.http().getWebServiceMessageSender();
assertRequestFactoryInstanceOf(sender, HttpComponentsClientHttpRequestFactory.class);
}
@Test
@ClassPathExclusions("httpclient5-*.jar")
void httpWhenDetectedJetty() {
WebServiceMessageSender sender = WebServiceMessageSenderFactory.http().getWebServiceMessageSender();
assertRequestFactoryInstanceOf(sender, JettyClientHttpRequestFactory.class);
}
@Test
@ClassPathExclusions({ "httpclient5-*.jar", "jetty-client-*.jar" })
void httpWhenDetectedReactor() {
WebServiceMessageSender sender = WebServiceMessageSenderFactory.http().getWebServiceMessageSender();
assertRequestFactoryInstanceOf(sender, ReactorClientHttpRequestFactory.class);
}
@Test
@ClassPathExclusions({ "httpclient5-*.jar", "jetty-client-*.jar", "reactor-netty-http-*.jar" })
void httpWhenDetectedJdk() {
WebServiceMessageSender sender = WebServiceMessageSenderFactory.http().getWebServiceMessageSender();
assertRequestFactoryInstanceOf(sender, JdkClientHttpRequestFactory.class);
}
@Test
@ClassPathExclusions("httpclient5-*.jar")
void httpWithSettingsUsesSettings() {
ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.defaults()
.withConnectTimeout(Duration.ofSeconds(5))
.withReadTimeout(Duration.ofSeconds(2));
WebServiceMessageSender sender = WebServiceMessageSenderFactory.http(settings).getWebServiceMessageSender();
assertTimeoutsOnJetty(sender);
}
@Test
void httpWithFactoryAndSettingsUsesFactoryAndSettings() {
ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.defaults()
.withConnectTimeout(Duration.ofSeconds(5))
.withReadTimeout(Duration.ofSeconds(2));
WebServiceMessageSender sender = WebServiceMessageSenderFactory
.http(ClientHttpRequestFactoryBuilder.jetty(), settings)
.getWebServiceMessageSender();
assertTimeoutsOnJetty(sender);
}
@Test
void httpWithFactoryAndSettingsWhenFactoryIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> WebServiceMessageSenderFactory.http(null, null))
.withMessage("'requestFactoryBuilder' must not be null");
}
private void assertTimeoutsOnJetty(WebServiceMessageSender sender) {
ClientHttpRequestFactory requestFactory = getRequestFactory(sender);
HttpClient client = (HttpClient) ReflectionTestUtils.getField(requestFactory, "httpClient");
assertThat(client).isNotNull();
assertThat(client.getConnectTimeout()).isEqualTo(5000);
assertThat(requestFactory).hasFieldOrPropertyWithValue("readTimeout", 2000L);
}
private void assertRequestFactoryInstanceOf(WebServiceMessageSender sender, Class<?> expectedRequestFactoryType) {
assertThat(getRequestFactory(sender)).isInstanceOf(expectedRequestFactoryType);
}
private ClientHttpRequestFactory getRequestFactory(WebServiceMessageSender sender) {
assertThat(sender).isInstanceOf(ClientHttpRequestMessageSender.class);
ClientHttpRequestFactory requestFactory = ((ClientHttpRequestMessageSender) sender).getRequestFactory();
return requestFactory;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2023 the original author or authors.
* Copyright 2012-2024 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,6 +30,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;
import org.springframework.ws.WebServiceMessageFactory;
@@ -53,6 +54,7 @@ import static org.mockito.Mockito.spy;
*
* @author Stephane Nicoll
* @author Dmytro Nosan
* @author Phillip Webb
*/
@ExtendWith(MockitoExtension.class)
class WebServiceTemplateBuilderTests {
@@ -77,7 +79,7 @@ class WebServiceTemplateBuilderTests {
WebServiceTemplate webServiceTemplate = this.builder.build();
assertThat(webServiceTemplate.getMessageSenders()).hasSize(1);
WebServiceMessageSender messageSender = webServiceTemplate.getMessageSenders()[0];
assertHttpComponentsRequestFactory(messageSender);
assertRequestFactoryInstanceOf(messageSender, HttpComponentsClientHttpRequestFactory.class);
}
@Test
@@ -87,6 +89,16 @@ class WebServiceTemplateBuilderTests {
assertThat(webServiceTemplate.getMessageSenders()[0]).isInstanceOf(HttpUrlConnectionMessageSender.class);
}
@Test
void httpMessageSenderFactoryUsesFactory() {
WebServiceTemplate webServiceTemplate = this.builder
.httpMessageSenderFactory(() -> new ClientHttpRequestMessageSender(new JdkClientHttpRequestFactory()))
.build();
assertThat(webServiceTemplate.getMessageSenders()).hasSize(1);
WebServiceMessageSender messageSender = webServiceTemplate.getMessageSenders()[0];
assertRequestFactoryInstanceOf(messageSender, JdkClientHttpRequestFactory.class);
}
@Test
void messageSendersWhenSendersAreAreNullShouldThrowException() {
assertThatIllegalArgumentException()
@@ -334,11 +346,11 @@ class WebServiceTemplateBuilderTests {
assertThat(webServiceTemplate.getDestinationProvider()).isEqualTo(destinationProvider);
}
private void assertHttpComponentsRequestFactory(WebServiceMessageSender messageSender) {
private void assertRequestFactoryInstanceOf(WebServiceMessageSender messageSender, Class<?> type) {
assertThat(messageSender).isInstanceOf(ClientHttpRequestMessageSender.class);
ClientHttpRequestMessageSender sender = (ClientHttpRequestMessageSender) messageSender;
ClientHttpRequestFactory requestFactory = sender.getRequestFactory();
assertThat(requestFactory).isInstanceOf(HttpComponentsClientHttpRequestFactory.class);
assertThat(requestFactory).isInstanceOf(type);
}
}