From dffa62c9a20a5cb00d5b991872d7eb66cb5820d9 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Fri, 31 Jan 2014 16:00:22 +0100 Subject: [PATCH] WSMessageSender based on ClientHttpRequestFactory Introduced an implementation of WebServiceSender that wraps ClientHttpRequestFactory, as found in Spring 3. Issue: SWS-859 --- .../http/AbstractHttpSenderConnection.java | 5 +- .../http/ClientHttpRequestConnection.java | 126 ++++++++++++++++++ .../http/ClientHttpRequestMessageSender.java | 66 +++++++++ .../http/HttpUrlConnectionMessageSender.java | 10 +- ...tpRequestMessageSenderIntegrationTest.java | 26 ++++ 5 files changed, 226 insertions(+), 7 deletions(-) create mode 100644 spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestConnection.java create mode 100644 spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSender.java create mode 100644 spring-ws-core/src/test/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSenderIntegrationTest.java diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java index 3ca623e9..655a827b 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/AbstractHttpSenderConnection.java @@ -93,7 +93,8 @@ public abstract class AbstractHttpSenderConnection extends AbstractSenderConnect Iterator iterator = getResponseHeaders(HttpTransportConstants.HEADER_CONTENT_ENCODING); if (iterator.hasNext()) { String encodingHeader = iterator.next(); - return encodingHeader.toLowerCase().indexOf(HttpTransportConstants.CONTENT_ENCODING_GZIP) != -1; + return encodingHeader.toLowerCase() + .contains(HttpTransportConstants.CONTENT_ENCODING_GZIP); } return false; } @@ -123,7 +124,7 @@ public abstract class AbstractHttpSenderConnection extends AbstractSenderConnect Iterator iterator = getResponseHeaders(HttpTransportConstants.HEADER_CONTENT_TYPE); if (iterator.hasNext()) { String contentType = iterator.next().toLowerCase(); - return contentType.indexOf("xml") != -1; + return contentType.contains("xml"); } return false; } diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestConnection.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestConnection.java new file mode 100644 index 00000000..91466357 --- /dev/null +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestConnection.java @@ -0,0 +1,126 @@ +/* + * Copyright 2005-2014 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 + * + * http://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.io.InputStream; +import java.io.OutputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.http.entity.ByteArrayEntity; + +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpResponse; +import org.springframework.util.Assert; +import org.springframework.ws.WebServiceMessage; + +/** + * Implementation of the {@link WebServiceConnection} interface that is based on the + * Spring 3 {@link ClientHttpRequest} and {@link ClientHttpResponse}. + * + * @author Krzysztof Trojan + * @author Arjen Poutsma + * @since 2.2 + */ +public class ClientHttpRequestConnection extends AbstractHttpSenderConnection { + + private final ClientHttpRequest request; + + private ClientHttpResponse response; + + public ClientHttpRequestConnection(ClientHttpRequest request) { + Assert.notNull(request, "'request' must not be null"); + this.request = request; + } + + public ClientHttpRequest getClientHttpRequest() { + return request; + } + + public ClientHttpResponse getClientHttpResponse() { + return response; + } + + // URI + + public URI getUri() throws URISyntaxException { + return request.getURI(); + } + + // Sending request + + @Override + protected void addRequestHeader(String name, String value) throws IOException { + request.getHeaders().add(name, value); + } + + @Override + protected OutputStream getRequestOutputStream() throws IOException { + return request.getBody(); + } + + @Override + protected void onSendAfterWrite(WebServiceMessage message) throws IOException { + response = request.execute(); + } + + // Receiving response + + @Override + protected long getResponseContentLength() throws IOException { + return response.getHeaders().getContentLength(); + } + + @Override + protected Iterator getResponseHeaderNames() throws IOException { + return response.getHeaders().keySet().iterator(); + } + + @Override + protected Iterator getResponseHeaders(String name) throws IOException { + List headers = response.getHeaders().get(name); + return headers != null ? headers.iterator() : + Collections.emptyList().iterator(); + } + + @Override + protected int getResponseCode() throws IOException { + return response.getStatusCode().value(); + } + + @Override + protected String getResponseMessage() throws IOException { + return response.getStatusText(); + } + + @Override + protected InputStream getRawResponseInputStream() throws IOException { + return response.getBody(); + } + + @Override + protected void onClose() throws IOException { + if (response != null) { + response.close(); + } + } + +} diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSender.java new file mode 100644 index 00000000..d3a51089 --- /dev/null +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSender.java @@ -0,0 +1,66 @@ +/* + * Copyright 2005-2014 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 + * + * http://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.springframework.http.HttpMethod; +import org.springframework.http.client.ClientHttpRequest; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.util.Assert; +import org.springframework.ws.transport.WebServiceConnection; + +/** + * {@code WebServiceMessageSender} implementation based on the + * {@link ClientHttpRequestFactory} introduced in Spring 3. + * + * @author Krzysztof Trojan + * @author Arjen Poutsma + * @since 2.2 + */ +public class ClientHttpRequestMessageSender extends AbstractHttpWebServiceMessageSender { + + private ClientHttpRequestFactory requestFactory; + + public ClientHttpRequestMessageSender() { + this(new SimpleClientHttpRequestFactory()); + } + + public ClientHttpRequestMessageSender(ClientHttpRequestFactory requestFactory) { + setRequestFactory(requestFactory); + } + + public ClientHttpRequestFactory getRequestFactory() { + return requestFactory; + } + + public void setRequestFactory(ClientHttpRequestFactory requestFactory) { + Assert.notNull(requestFactory, "'requestFactory' must not be null"); + this.requestFactory = requestFactory; + } + + public WebServiceConnection createConnection(URI uri) throws IOException { + ClientHttpRequest request = requestFactory.createRequest(uri, HttpMethod.POST); + if (isAcceptGzipEncoding()) { + request.getHeaders().add(HttpTransportConstants.HEADER_ACCEPT_ENCODING, + HttpTransportConstants.CONTENT_ENCODING_GZIP); + } + return new ClientHttpRequestConnection(request); + } +} diff --git a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java index 61190afa..7e1daa71 100644 --- a/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java +++ b/spring-ws-core/src/main/java/org/springframework/ws/transport/http/HttpUrlConnectionMessageSender.java @@ -25,12 +25,12 @@ import java.net.URLConnection; import org.springframework.ws.transport.WebServiceConnection; /** - * WebServiceMessageSender implementation that uses standard J2SE facilities to execute POST requests, - * without support for HTTP authentication or advanced configuration options. + * {@code WebServiceMessageSender} implementation that uses standard J2SE facilities to + * execute POST requests, without support for HTTP authentication or advanced + * configuration options. *

- * Designed for easy subclassing, customizing specific template methods. However, consider {@link - * CommonsHttpMessageSender} for more sophisticated needs: the J2SE HttpURLConnection is rather limited in - * its capabilities. + * Consider {@link HttpComponentsMessageSender} for more sophisticated needs: this class + * is rather limited in its capabilities. * * @author Arjen Poutsma * @see java.net.HttpURLConnection diff --git a/spring-ws-core/src/test/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSenderIntegrationTest.java b/spring-ws-core/src/test/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSenderIntegrationTest.java new file mode 100644 index 00000000..7da6aa25 --- /dev/null +++ b/spring-ws-core/src/test/java/org/springframework/ws/transport/http/ClientHttpRequestMessageSenderIntegrationTest.java @@ -0,0 +1,26 @@ +/* + * Copyright 2005-2014 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 + * + * http://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; + +public class ClientHttpRequestMessageSenderIntegrationTest + extends AbstractHttpWebServiceMessageSenderIntegrationTestCase { + + @Override + protected AbstractHttpWebServiceMessageSender createMessageSender() { + return new ClientHttpRequestMessageSender(); + } +} \ No newline at end of file