Skip to content

Commit 6356e90

Browse files
committed
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
1 parent 022f3cb commit 6356e90

File tree

11 files changed

+342
-81
lines changed

11 files changed

+342
-81
lines changed

spring-boot-project/spring-boot-docs/src/main/java/org/springframework/boot/docs/io/webservices/template/MyWebServiceTemplateConfiguration.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,7 +18,8 @@
1818

1919
import java.time.Duration;
2020

21-
import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder;
21+
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
22+
import org.springframework.boot.webservices.client.WebServiceMessageSenderFactory;
2223
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder;
2324
import org.springframework.context.annotation.Bean;
2425
import org.springframework.context.annotation.Configuration;
@@ -30,13 +31,11 @@ public class MyWebServiceTemplateConfiguration {
3031

3132
@Bean
3233
public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) {
33-
// @formatter:off
34-
WebServiceMessageSender sender = new HttpWebServiceMessageSenderBuilder()
35-
.setConnectTimeout(Duration.ofSeconds(5))
36-
.setReadTimeout(Duration.ofSeconds(2))
37-
.build();
34+
ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.defaults()
35+
.withConnectTimeout(Duration.ofSeconds(2))
36+
.withReadTimeout(Duration.ofSeconds(2));
37+
WebServiceMessageSender sender = WebServiceMessageSenderFactory.http(settings).getWebServiceMessageSender();
3838
return builder.messageSenders(sender).build();
39-
// @formatter:on
4039
}
4140

4241
}

spring-boot-project/spring-boot-docs/src/main/kotlin/org/springframework/boot/docs/io/webservices/template/MyWebServiceTemplateConfiguration.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616

1717
package org.springframework.boot.docs.io.webservices.template
1818

19-
import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder
19+
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings
20+
import org.springframework.boot.webservices.client.WebServiceMessageSenderFactory
2021
import org.springframework.boot.webservices.client.WebServiceTemplateBuilder
2122
import org.springframework.context.annotation.Bean
2223
import org.springframework.context.annotation.Configuration
@@ -28,11 +29,11 @@ class MyWebServiceTemplateConfiguration {
2829

2930
@Bean
3031
fun webServiceTemplate(builder: WebServiceTemplateBuilder): WebServiceTemplate {
31-
val sender = HttpWebServiceMessageSenderBuilder()
32-
.setConnectTimeout(Duration.ofSeconds(5))
33-
.setReadTimeout(Duration.ofSeconds(2))
34-
.build()
35-
return builder.messageSenders(sender).build()
32+
val settings = ClientHttpRequestFactorySettings.defaults()
33+
.withConnectTimeout(Duration.ofSeconds(2))
34+
.withReadTimeout(Duration.ofSeconds(2));
35+
val sender = WebServiceMessageSenderFactory.http(settings).getWebServiceMessageSender();
36+
return builder.messageSenders(sender).build();
3637
}
3738

3839
}

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/webservices/client/HttpWebServiceMessageSenderBuilder.java

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -20,38 +20,37 @@
2020
import java.util.function.Function;
2121
import java.util.function.Supplier;
2222

23+
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
24+
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
25+
import org.springframework.boot.http.client.JdkClientHttpRequestFactoryBuilder;
2326
import org.springframework.boot.ssl.SslBundle;
24-
import org.springframework.boot.web.client.ClientHttpRequestFactories;
25-
import org.springframework.boot.web.client.ClientHttpRequestFactorySettings;
2627
import org.springframework.http.client.ClientHttpRequestFactory;
2728
import org.springframework.util.Assert;
2829
import org.springframework.ws.transport.WebServiceMessageSender;
29-
import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;
3030

3131
/**
3232
* {@link WebServiceMessageSender} builder that can detect a suitable HTTP library based
3333
* on the classpath.
3434
*
3535
* @author Stephane Nicoll
3636
* @since 2.1.0
37+
* @deprecated since 3.4.0 in favor of
38+
* {@link WebServiceMessageSenderFactory#http(ClientHttpRequestFactorySettings)}
3739
*/
40+
@Deprecated(since = "3.4.0", forRemoval = true)
3841
public class HttpWebServiceMessageSenderBuilder {
3942

40-
private Duration connectTimeout;
43+
private ClientHttpRequestFactoryBuilder<?> requestFactoryBuilder;
4144

42-
private Duration readTimeout;
43-
44-
private SslBundle sslBundle;
45-
46-
private Function<ClientHttpRequestFactorySettings, ClientHttpRequestFactory> requestFactory;
45+
private ClientHttpRequestFactorySettings requestFactorySettings = ClientHttpRequestFactorySettings.defaults();
4746

4847
/**
4948
* Set the connection timeout.
5049
* @param connectTimeout the connection timeout
5150
* @return a new builder instance
5251
*/
5352
public HttpWebServiceMessageSenderBuilder setConnectTimeout(Duration connectTimeout) {
54-
this.connectTimeout = connectTimeout;
53+
this.requestFactorySettings = this.requestFactorySettings.withConnectTimeout(connectTimeout);
5554
return this;
5655
}
5756

@@ -61,7 +60,7 @@ public HttpWebServiceMessageSenderBuilder setConnectTimeout(Duration connectTime
6160
* @return a new builder instance
6261
*/
6362
public HttpWebServiceMessageSenderBuilder setReadTimeout(Duration readTimeout) {
64-
this.readTimeout = readTimeout;
63+
this.requestFactorySettings = this.requestFactorySettings.withReadTimeout(readTimeout);
6564
return this;
6665
}
6766

@@ -71,7 +70,7 @@ public HttpWebServiceMessageSenderBuilder setReadTimeout(Duration readTimeout) {
7170
* @return a new builder instance
7271
*/
7372
public HttpWebServiceMessageSenderBuilder sslBundle(SslBundle sslBundle) {
74-
this.sslBundle = sslBundle;
73+
this.requestFactorySettings = this.requestFactorySettings.withSslBundle(sslBundle);
7574
return this;
7675
}
7776

@@ -84,7 +83,7 @@ public HttpWebServiceMessageSenderBuilder sslBundle(SslBundle sslBundle) {
8483
public HttpWebServiceMessageSenderBuilder requestFactory(
8584
Supplier<ClientHttpRequestFactory> requestFactorySupplier) {
8685
Assert.notNull(requestFactorySupplier, "RequestFactorySupplier must not be null");
87-
this.requestFactory = (settings) -> ClientHttpRequestFactories.get(requestFactorySupplier, settings);
86+
this.requestFactoryBuilder = ClientHttpRequestFactoryBuilder.of(requestFactorySupplier);
8887
return this;
8988
}
9089

@@ -99,7 +98,21 @@ public HttpWebServiceMessageSenderBuilder requestFactory(
9998
public HttpWebServiceMessageSenderBuilder requestFactory(
10099
Function<ClientHttpRequestFactorySettings, ClientHttpRequestFactory> requestFactoryFunction) {
101100
Assert.notNull(requestFactoryFunction, "RequestFactoryFunction must not be null");
102-
this.requestFactory = requestFactoryFunction;
101+
this.requestFactoryBuilder = requestFactoryFunction::apply;
102+
return this;
103+
}
104+
105+
/**
106+
* Set the {@link ClientHttpRequestFactoryBuilder} to use when creating the HTTP-based
107+
* {@link WebServiceMessageSender}.
108+
* @param requestFactoryBuilder the {@link ClientHttpRequestFactoryBuilder} to use
109+
* @return this builder instance
110+
* @since 3.4.0
111+
*/
112+
public HttpWebServiceMessageSenderBuilder requestFactoryBuilder(
113+
ClientHttpRequestFactoryBuilder<?> requestFactoryBuilder) {
114+
Assert.notNull(requestFactoryBuilder, "ClientHttpRequestFactoryBuilder must not be null");
115+
this.requestFactoryBuilder = requestFactoryBuilder;
103116
return this;
104117
}
105118

@@ -108,14 +121,21 @@ public HttpWebServiceMessageSenderBuilder requestFactory(
108121
* @return the {@link WebServiceMessageSender} instance
109122
*/
110123
public WebServiceMessageSender build() {
111-
return new ClientHttpRequestMessageSender(getRequestFactory());
124+
ClientHttpRequestFactoryBuilder<?> requestFactoryBuilder = getOrDetectRequestFactoryBuilder();
125+
return WebServiceMessageSenderFactory.http(requestFactoryBuilder, this.requestFactorySettings)
126+
.getWebServiceMessageSender();
112127
}
113128

114-
private ClientHttpRequestFactory getRequestFactory() {
115-
ClientHttpRequestFactorySettings settings = new ClientHttpRequestFactorySettings(this.connectTimeout,
116-
this.readTimeout, this.sslBundle);
117-
return (this.requestFactory != null) ? this.requestFactory.apply(settings)
118-
: ClientHttpRequestFactories.get(settings);
129+
private ClientHttpRequestFactoryBuilder<?> getOrDetectRequestFactoryBuilder() {
130+
if (this.requestFactoryBuilder != null) {
131+
return this.requestFactoryBuilder;
132+
}
133+
ClientHttpRequestFactoryBuilder<?> builder = ClientHttpRequestFactoryBuilder.detect();
134+
if (builder instanceof JdkClientHttpRequestFactoryBuilder) {
135+
// Same logic as earlier versions which did not support JDK client factories
136+
return ClientHttpRequestFactoryBuilder.simple();
137+
}
138+
return builder;
119139
}
120140

121141
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright 2012-2024 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.boot.webservices.client;
18+
19+
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
20+
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
21+
import org.springframework.http.client.ClientHttpRequestFactory;
22+
import org.springframework.util.Assert;
23+
import org.springframework.ws.transport.WebServiceMessageSender;
24+
import org.springframework.ws.transport.http.ClientHttpRequestMessageSender;
25+
26+
/**
27+
* Factory that can be used to create a {@link WebServiceMessageSender}.
28+
*
29+
* @author Phillip Webb
30+
* @since 3.4.0
31+
*/
32+
@FunctionalInterface
33+
public interface WebServiceMessageSenderFactory {
34+
35+
/**
36+
* Return a new {@link WebServiceMessageSender} instance.
37+
* @return the web service message sender
38+
*/
39+
WebServiceMessageSender getWebServiceMessageSender();
40+
41+
/**
42+
* Returns a factory that will create a {@link ClientHttpRequestMessageSender} backed
43+
* by a detected {@link ClientHttpRequestFactory}.
44+
* @return a new {@link WebServiceMessageSenderFactory}
45+
*/
46+
static WebServiceMessageSenderFactory http() {
47+
return http(ClientHttpRequestFactoryBuilder.detect(), null);
48+
}
49+
50+
/**
51+
* Returns a factory that will create a {@link ClientHttpRequestMessageSender} backed
52+
* by a detected {@link ClientHttpRequestFactory}.
53+
* @param requestFactorySettings the setting to apply
54+
* @return a new {@link WebServiceMessageSenderFactory}
55+
*/
56+
static WebServiceMessageSenderFactory http(ClientHttpRequestFactorySettings requestFactorySettings) {
57+
return http(ClientHttpRequestFactoryBuilder.detect(), requestFactorySettings);
58+
}
59+
60+
/**
61+
* Returns a factory that will create a {@link ClientHttpRequestMessageSender} backed
62+
* by a {@link ClientHttpRequestFactory} created from the given
63+
* {@link ClientHttpRequestFactoryBuilder}.
64+
* @param requestFactoryBuilder the request factory builder to use
65+
* @param requestFactorySettings the settings to apply
66+
* @return a new {@link WebServiceMessageSenderFactory}
67+
*/
68+
static WebServiceMessageSenderFactory http(ClientHttpRequestFactoryBuilder<?> requestFactoryBuilder,
69+
ClientHttpRequestFactorySettings requestFactorySettings) {
70+
Assert.notNull(requestFactoryBuilder, "'requestFactoryBuilder' must not be null");
71+
return () -> new ClientHttpRequestMessageSender(requestFactoryBuilder.build(requestFactorySettings));
72+
}
73+
74+
}

0 commit comments

Comments
 (0)