diff --git a/pom.xml b/pom.xml index c3ef4c783..1a180d336 100644 --- a/pom.xml +++ b/pom.xml @@ -275,6 +275,8 @@ + + diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5ClientFactory.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5ClientFactory.java index 584909498..191ba33e3 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5ClientFactory.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5ClientFactory.java @@ -33,6 +33,7 @@ import org.apache.hc.core5.http.HttpHost; import org.apache.hc.core5.util.Timeout; import org.springframework.beans.factory.FactoryBean; +import org.springframework.ws.client.support.interceptor.ClientInterceptor; /** * {@link FactoryBean} to set up a {@link CloseableHttpClient} using HttpComponents HttpClient 5. @@ -43,6 +44,18 @@ */ public class HttpComponents5ClientFactory implements FactoryBean { + /** + * AuthScope to match any Host. + *

+ * HEADS-UP: ANY has been removed from {@link AuthScope} since httpcomponents version 5.x. It has been + * redefined here to ease migration from httpcomponents 4. The associated functionality might be removed in a future + * version of apache httpcomponents. Consider using a {@link ClientInterceptor} to implement http client agnostic + * preemptive basic auth. + * + * @see AuthScope#AuthScope(String, String, int, String, String) + */ + public static final AuthScope ANY = new AuthScope(null, null, -1, null, null); + private static final Duration DEFAULT_CONNECTION_TIMEOUT = Duration.ofSeconds(60); private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofSeconds(60); @@ -53,7 +66,7 @@ public class HttpComponents5ClientFactory implements FactoryBean - * By default, the {@link AuthScope#ANY} is used. + * By default, the {@link #ANY} is used. * * @see #setCredentials(Credentials) */ diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5MessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5MessageSender.java index 27bc7c8e5..d0b96838c 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5MessageSender.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpComponents5MessageSender.java @@ -34,6 +34,7 @@ import org.apache.hc.core5.http.HttpRequest; import org.apache.hc.core5.http.HttpRequestInterceptor; import org.apache.hc.core5.http.protocol.HttpContext; + import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; @@ -178,7 +179,10 @@ public void setMaxConnectionsPerHost(Map maxConnectionsPerHost) @Override public void afterPropertiesSet() throws Exception { - this.httpClient = clientFactory.getObject(); + + if (this.clientFactory != null) { + this.httpClient = clientFactory.getObject(); + } } @Override diff --git a/spring-ws-core/src/test/java/org/springframework/ws/transport/http/HttpComponents5MessageSenderTest.java b/spring-ws-core/src/test/java/org/springframework/ws/transport/http/HttpComponents5MessageSenderTest.java new file mode 100644 index 000000000..75f7ee065 --- /dev/null +++ b/spring-ws-core/src/test/java/org/springframework/ws/transport/http/HttpComponents5MessageSenderTest.java @@ -0,0 +1,33 @@ +package org.springframework.ws.transport.http; + +import java.time.Duration; + +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.*; + +class HttpComponents5MessageSenderTest { + + @Test + void afterPropertiesSet_createHttpClient() throws Exception { + HttpComponents5MessageSender messageSender = new HttpComponents5MessageSender(); + assertThat(messageSender.getHttpClient()).isNull(); + Duration timeout = Duration.ofSeconds(1); + assertThatCode(() -> messageSender.setConnectionTimeout(timeout)).doesNotThrowAnyException(); + messageSender.afterPropertiesSet(); + assertThat(messageSender.getHttpClient()).isNotNull(); + } + + @Test + void afterPropertiesSet_httpClientAlreadySet() throws Exception { + CloseableHttpClient httpClient = HttpClientBuilder.create().build(); + HttpComponents5MessageSender messageSender = new HttpComponents5MessageSender(httpClient); + Duration timeout = Duration.ofSeconds(1); + assertThatCode(() -> messageSender.setConnectionTimeout(timeout)).isInstanceOf(IllegalStateException.class); + messageSender.afterPropertiesSet(); + assertThat(messageSender.getHttpClient()).isSameAs(httpClient); + } + +} \ No newline at end of file