Skip to content
Closed
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,11 @@
</argLine>
</configuration>
</plugin>

<plugin>
<groupId>io.spring.javaformat</groupId>
<artifactId>spring-javaformat-maven-plugin</artifactId>
<version>0.0.38</version>
</plugin>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We aren't adopting this plugin. Essentially, I am using https://github.com/spring-projects/spring-data-build/tree/main/etc/ide as the basis for any/all polishing going forward.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No offense, I just accidentally committed the pom ...

</plugins>
</build>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManagerBuilder;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.util.Timeout;

import org.springframework.beans.factory.FactoryBean;

/**
Expand Down Expand Up @@ -66,10 +67,12 @@ public class HttpComponents5ClientFactory implements FactoryBean<CloseableHttpCl
private PoolingHttpClientConnectionManagerBuilderCustomizer connectionManagerBuilderCustomizer;

/**
* Sets the credentials to be used. If not set, no authentication is done.
* Sets the credentials to be used. If not set, no authentication is done. Only used
* when the {@code authScope} property has been set.
*
* @see org.apache.hc.client5.http.auth.UsernamePasswordCredentials
* @see org.apache.hc.client5.http.auth.NTCredentials
* @see #setAuthScope(AuthScope)
*/
public void setCredentials(Credentials credentials) {
this.credentials = credentials;
Expand All @@ -78,7 +81,6 @@ public void setCredentials(Credentials credentials) {
/**
* Sets the authentication scope to be used. Only used when the {@code credentials} property has been set.
* <p>
* By default, the {@link AuthScope#ANY} is used.
*
* @see #setCredentials(Credentials)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,20 @@
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;
import org.springframework.ws.transport.WebServiceConnection;

/**
* {@code WebServiceMessageSender} implementation that uses <a href="http://hc.apache.org/httpcomponents-client">Apache
* HttpClient</a> to execute POST requests.
* {@code WebServiceMessageSender} implementation that uses
* <a href="http://hc.apache.org/httpcomponents-client">Apache HttpClient</a> to execute
* POST requests.
* <p>
* Allows to use a pre-configured HttpClient instance, potentially with authentication, HTTP connection pooling, etc.
* Authentication can also be set by injecting a {@link Credentials} instance (such as the
* Allows to use a pre-configured HttpClient instance, potentially with authentication,
* HTTP connection pooling, etc. Authentication can also be set by injecting a
* {@link Credentials} instance (such as the
* {@link org.apache.hc.client5.http.auth.UsernamePasswordCredentials}).
*
* @author Alan Stewart
Expand All @@ -65,8 +68,8 @@ public class HttpComponents5MessageSender extends AbstractHttpWebServiceMessageS
private HttpComponents5ClientFactory clientFactory;

/**
* Create a new instance of the {@code HttpClientMessageSender} with a default {@link HttpClient} that uses a default
* {@link PoolingHttpClientConnectionManager}.
* Create a new instance of the {@code HttpClientMessageSender} with a default
* {@link HttpClient} that uses a default {@link PoolingHttpClientConnectionManager}.
*/
public HttpComponents5MessageSender() {

Expand All @@ -76,12 +79,13 @@ public HttpComponents5MessageSender() {
}

/**
* Create a new instance of the {@link HttpComponents5MessageSender} with the given {@link HttpClient} instance.
* Create a new instance of the {@link HttpComponents5MessageSender} with the given
* {@link HttpClient} instance.
* <p>
* This constructor does not change the given {@code HttpClient} in any way. As such, it does not set timeouts, nor
* does it {@linkplain HttpClientBuilder#addRequestInterceptorFirst(HttpRequestInterceptor) add} the
* {@link RemoveSoapHeadersInterceptor}.
*
* This constructor does not change the given {@code HttpClient} in any way. As such,
* it does not set timeouts, nor does it
* {@linkplain HttpClientBuilder#addRequestInterceptorFirst(HttpRequestInterceptor)
* add} the {@link RemoveSoapHeadersInterceptor}.
* @param httpClient the HttpClient instance to use for this sender
*/
public HttpComponents5MessageSender(HttpClient httpClient) {
Expand Down Expand Up @@ -178,7 +182,10 @@ public void setMaxConnectionsPerHost(Map<String, String> maxConnectionsPerHost)

@Override
public void afterPropertiesSet() throws Exception {
this.httpClient = clientFactory.getObject();

if (null != this.clientFactory) {
this.httpClient = clientFactory.getObject();
}
}

@Override
Expand All @@ -187,7 +194,8 @@ public WebServiceConnection createConnection(URI uri) throws IOException {
HttpPost httpPost = new HttpPost(uri);

if (isAcceptGzipEncoding()) {
httpPost.addHeader(HttpTransportConstants.HEADER_ACCEPT_ENCODING, HttpTransportConstants.CONTENT_ENCODING_GZIP);
httpPost.addHeader(HttpTransportConstants.HEADER_ACCEPT_ENCODING,
HttpTransportConstants.CONTENT_ENCODING_GZIP);
}

HttpContext httpContext = createContext(uri);
Expand All @@ -196,9 +204,8 @@ public WebServiceConnection createConnection(URI uri) throws IOException {
}

/**
* Template method that allows for creation of an {@link HttpContext} for the given uri. Default implementation returns
* {@code null}.
*
* Template method that allows for creation of an {@link HttpContext} for the given
* uri. Default implementation returns {@code null}.
* @param uri the URI to create the context for
* @return the context, or {@code null}
*/
Expand All @@ -209,15 +216,16 @@ protected HttpContext createContext(URI uri) {
@Override
public void destroy() throws Exception {

if (getHttpClient()instanceof CloseableHttpClient client) {
if (getHttpClient() instanceof CloseableHttpClient client) {
client.close();
}
}

/**
* HttpClient {@link HttpRequestInterceptor} implementation that removes {@code Content-Length} and
* {@code Transfer-Encoding} headers from the request. Necessary, because some SAAJ and other SOAP implementations set
* these headers themselves, and HttpClient throws an exception if they have been set.
* HttpClient {@link HttpRequestInterceptor} implementation that removes
* {@code Content-Length} and {@code Transfer-Encoding} headers from the request.
* Necessary, because some SAAJ and other SOAP implementations set these headers
* themselves, and HttpClient throws an exception if they have been set.
*/
public static class RemoveSoapHeadersInterceptor implements HttpRequestInterceptor {

Expand All @@ -233,5 +241,7 @@ public void process(HttpRequest request, EntityDetails entityDetails, HttpContex
request.removeHeaders(HttpHeaders.CONTENT_LENGTH);
}
}

}

}
Original file line number Diff line number Diff line change
@@ -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);
}

}