Simplify HttpComponents5MessageSender

Previously, HttpComponents5MessageSender can be configured to use both
a custom HttpClient or configure one using a number of convenient
properties. This setup creates an odd arrangement where calling those
convenient methods once an HttpClient is set throws an exception as
the implementation supports one or the other.

This commit moves the first use case in a simple implementation that
only accepts a custom HttpClient or the state of
HttpComponents5ClientFactory for convenience and discoverability.

Specifying an HttpComponents5MessageSender is deprecated as a result.

Closes gh-1519
This commit is contained in:
Stéphane Nicoll
2025-04-08 12:59:03 +02:00
parent cf9295b887
commit f250abb0cf
7 changed files with 286 additions and 103 deletions

View File

@@ -23,22 +23,19 @@ import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
class HttpComponents5ContentTypeIntegrationTest
extends AbstractHttpWebServiceMessageSenderIntegrationTest<HttpComponents5MessageSender> {
extends AbstractHttpWebServiceMessageSenderIntegrationTest<AbstractHttpComponents5MessageSender> {
@Override
protected HttpComponents5MessageSender createMessageSender() {
protected AbstractHttpComponents5MessageSender createMessageSender() {
ExecChainHandler testHandler = (request, scope, chain) -> {
assertThat(request.getEntity().getContentType()).isNotBlank();
return chain.proceed(request, scope);
};
HttpClient client = HttpClientBuilder.create()
.addRequestInterceptorFirst(new HttpComponents5MessageSender.RemoveSoapHeadersInterceptor())
.addExecInterceptorFirst("handler with assertion", testHandler)
.build();
return new HttpComponents5MessageSender(client);
return new SimpleHttpComponents5MessageSender(client);
}
}

View File

@@ -44,6 +44,8 @@ class HttpComponents5MessageSenderTest {
}
@Test
@Deprecated
@SuppressWarnings("removal")
void afterPropertiesSetShouldUseAlreadyProvidedHttpClientIfAvailableWithConstructor() throws Exception {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpComponents5MessageSender messageSender = new HttpComponents5MessageSender(httpClient);
@@ -54,6 +56,8 @@ class HttpComponents5MessageSenderTest {
}
@Test
@Deprecated
@SuppressWarnings("removal")
void afterPropertiesSetShouldUseAlreadyProvidedHttpClientIfAvailableWithProperty() throws Exception {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
HttpComponents5MessageSender messageSender = new HttpComponents5MessageSender();

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2005-2025 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.ws.transport.http;
import java.io.IOException;
import java.net.URI;
import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
import org.junit.jupiter.api.Test;
import org.springframework.ws.transport.WebServiceConnection;
import org.springframework.ws.transport.http.HttpComponents5ClientFactory.HttpClientBuilderCustomizer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
/**
* Tests for {@link SimpleHttpComponents5MessageSender}.
*/
class SimpleHttpComponents5MessageSenderTest {
@Test
void createExposesHttpClient() {
HttpClient httpClient = HttpClientBuilder.create().build();
SimpleHttpComponents5MessageSender messageSender = new SimpleHttpComponents5MessageSender(httpClient);
assertThat(messageSender.getHttpClient()).isSameAs(httpClient);
}
@Test
void createWithNullFails() {
HttpClient httpClient = null;
assertThatIllegalArgumentException().isThrownBy(() -> new SimpleHttpComponents5MessageSender(httpClient));
}
@Test
void createWithFactory() throws Exception {
HttpComponents5ClientFactory factory = new HttpComponents5ClientFactory();
HttpClientBuilderCustomizer builderCustomizer = mock(HttpClientBuilderCustomizer.class);
factory.setClientBuilderCustomizer(builderCustomizer);
new SimpleHttpComponents5MessageSender(factory);
verify(builderCustomizer).customize(any());
}
@Test
void createConnectionUsesHttpClient() throws IOException {
HttpClient httpClient = HttpClientBuilder.create().build();
SimpleHttpComponents5MessageSender messageSender = new SimpleHttpComponents5MessageSender(httpClient);
WebServiceConnection webServiceConnection = messageSender
.createConnection(URI.create("https://ws.example.com"));
assertThat(webServiceConnection).isInstanceOfSatisfying(HttpComponents5Connection.class,
(connection) -> assertThat(connection).hasFieldOrPropertyWithValue("httpClient", httpClient));
}
}