diff --git a/spring-test/src/main/java/org/springframework/mock/http/client/MockAsyncClientHttpRequest.java b/spring-test/src/main/java/org/springframework/mock/http/client/MockAsyncClientHttpRequest.java deleted file mode 100644 index c082fce1b8..0000000000 --- a/spring-test/src/main/java/org/springframework/mock/http/client/MockAsyncClientHttpRequest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2017 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.mock.http.client; - -import java.io.IOException; -import java.net.URI; - -import org.springframework.http.HttpMethod; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.SettableListenableFuture; - -/** - * An extension of {@link MockClientHttpRequest} that also implements - * {@link org.springframework.http.client.AsyncClientHttpRequest} by wrapping the response in a - * {@link SettableListenableFuture}. - * - * @author Rossen Stoyanchev - * @author Sam Brannen - * @since 4.1 - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -public class MockAsyncClientHttpRequest extends MockClientHttpRequest implements org.springframework.http.client.AsyncClientHttpRequest { - - public MockAsyncClientHttpRequest() { - } - - public MockAsyncClientHttpRequest(HttpMethod httpMethod, URI uri) { - super(httpMethod, uri); - } - - - @Override - public ListenableFuture executeAsync() throws IOException { - SettableListenableFuture future = new SettableListenableFuture<>(); - future.set(execute()); - return future; - } - -} diff --git a/spring-test/src/main/java/org/springframework/test/web/client/MockMvcClientHttpRequestFactory.java b/spring-test/src/main/java/org/springframework/test/web/client/MockMvcClientHttpRequestFactory.java index 42c7a03cef..4c4592230d 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/MockMvcClientHttpRequestFactory.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/MockMvcClientHttpRequestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -16,7 +16,6 @@ package org.springframework.test.web.client; -import java.io.IOException; import java.net.URI; import java.nio.charset.StandardCharsets; import java.util.List; @@ -39,18 +38,10 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder /** * A {@link ClientHttpRequestFactory} for requests executed via {@link MockMvc}. * - *

As of 5.0 this class also implements - * {@link org.springframework.http.client.AsyncClientHttpRequestFactory - * AsyncClientHttpRequestFactory}. However note that - * {@link org.springframework.web.client.AsyncRestTemplate} and related classes - * have been deprecated at the same time. - * * @author Rossen Stoyanchev * @since 3.2 */ -@SuppressWarnings("deprecation") -public class MockMvcClientHttpRequestFactory - implements ClientHttpRequestFactory, org.springframework.http.client.AsyncClientHttpRequestFactory { +public class MockMvcClientHttpRequestFactory implements ClientHttpRequestFactory { private final MockMvc mockMvc; @@ -65,22 +56,12 @@ public class MockMvcClientHttpRequestFactory public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) { return new MockClientHttpRequest(httpMethod, uri) { @Override - public ClientHttpResponse executeInternal() throws IOException { + public ClientHttpResponse executeInternal() { return getClientHttpResponse(httpMethod, uri, getHeaders(), getBodyAsBytes()); } }; } - @Override - public org.springframework.http.client.AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod method) { - return new org.springframework.mock.http.client.MockAsyncClientHttpRequest(method, uri) { - @Override - protected ClientHttpResponse executeInternal() throws IOException { - return getClientHttpResponse(method, uri, getHeaders(), getBodyAsBytes()); - } - }; - } - private ClientHttpResponse getClientHttpResponse( HttpMethod httpMethod, URI uri, HttpHeaders requestHeaders, byte[] requestBody) { diff --git a/spring-test/src/main/java/org/springframework/test/web/client/MockRestServiceServer.java b/spring-test/src/main/java/org/springframework/test/web/client/MockRestServiceServer.java index d3c0cd7b41..8dbeff5a6c 100644 --- a/spring-test/src/main/java/org/springframework/test/web/client/MockRestServiceServer.java +++ b/spring-test/src/main/java/org/springframework/test/web/client/MockRestServiceServer.java @@ -25,7 +25,7 @@ import org.springframework.http.client.BufferingClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.http.client.ClientHttpResponse; -import org.springframework.lang.Nullable; +import org.springframework.mock.http.client.MockClientHttpRequest; import org.springframework.util.Assert; import org.springframework.web.client.RestTemplate; import org.springframework.web.client.support.RestGatewaySupport; @@ -64,7 +64,6 @@ import org.springframework.web.client.support.RestGatewaySupport; * @author Rossen Stoyanchev * @since 3.2 */ -@SuppressWarnings("deprecation") public final class MockRestServiceServer { private final RequestExpectationManager expectationManager; @@ -147,18 +146,6 @@ public final class MockRestServiceServer { return new DefaultBuilder(restTemplate); } - /** - * Return a builder for a {@code MockRestServiceServer} that should be used - * to reply to the given {@code AsyncRestTemplate}. - * @since 4.3 - * @deprecated see deprecation notice on - * {@link org.springframework.web.client.AsyncRestTemplate} itself - */ - @Deprecated - public static MockRestServiceServerBuilder bindTo(org.springframework.web.client.AsyncRestTemplate asyncRestTemplate) { - return new DefaultBuilder(asyncRestTemplate); - } - /** * Return a builder for a {@code MockRestServiceServer} that should be used * to reply to the given {@code RestGatewaySupport}. @@ -179,18 +166,6 @@ public final class MockRestServiceServer { return bindTo(restTemplate).build(); } - /** - * A shortcut for {@code bindTo(asyncRestTemplate).build()}. - * @param asyncRestTemplate the AsyncRestTemplate to set up for mock testing - * @return the created mock server - * @deprecated see deprecation notice on - * {@link org.springframework.web.client.AsyncRestTemplate} itself - */ - @Deprecated - public static MockRestServiceServer createServer(org.springframework.web.client.AsyncRestTemplate asyncRestTemplate) { - return bindTo(asyncRestTemplate).build(); - } - /** * A shortcut for {@code bindTo(restGateway).build()}. * @param restGateway the REST gateway to set up for mock testing @@ -226,8 +201,8 @@ public final class MockRestServiceServer { /** * Build the {@code MockRestServiceServer} and set up the underlying - * {@code RestTemplate} or {@code AsyncRestTemplate} with a - * {@link ClientHttpRequestFactory} that creates mock requests. + * {@code RestTemplate} with a {@link ClientHttpRequestFactory} that + * creates mock requests. */ MockRestServiceServer build(); @@ -241,12 +216,8 @@ public final class MockRestServiceServer { private static class DefaultBuilder implements MockRestServiceServerBuilder { - @Nullable private final RestTemplate restTemplate; - @Nullable - private final org.springframework.web.client.AsyncRestTemplate asyncRestTemplate; - private boolean ignoreExpectOrder; private boolean bufferContent; @@ -255,13 +226,6 @@ public final class MockRestServiceServer { public DefaultBuilder(RestTemplate restTemplate) { Assert.notNull(restTemplate, "RestTemplate must not be null"); this.restTemplate = restTemplate; - this.asyncRestTemplate = null; - } - - public DefaultBuilder(org.springframework.web.client.AsyncRestTemplate asyncRestTemplate) { - Assert.notNull(asyncRestTemplate, "AsyncRestTemplate must not be null"); - this.restTemplate = null; - this.asyncRestTemplate = asyncRestTemplate; } @Override @@ -290,16 +254,11 @@ public final class MockRestServiceServer { public MockRestServiceServer build(RequestExpectationManager manager) { MockRestServiceServer server = new MockRestServiceServer(manager); MockClientHttpRequestFactory factory = server.new MockClientHttpRequestFactory(); - if (this.restTemplate != null) { - if (this.bufferContent) { - this.restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(factory)); - } - else { - this.restTemplate.setRequestFactory(factory); - } + if (this.bufferContent) { + this.restTemplate.setRequestFactory(new BufferingClientHttpRequestFactory(factory)); } - if (this.asyncRestTemplate != null) { - this.asyncRestTemplate.setAsyncRequestFactory(factory); + else { + this.restTemplate.setRequestFactory(factory); } return server; } @@ -310,28 +269,18 @@ public final class MockRestServiceServer { * Mock ClientHttpRequestFactory that creates requests by iterating * over the list of expected {@link DefaultRequestExpectation}'s. */ - private class MockClientHttpRequestFactory implements ClientHttpRequestFactory, - org.springframework.http.client.AsyncClientHttpRequestFactory { + private class MockClientHttpRequestFactory implements ClientHttpRequestFactory { @Override public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) { return createRequestInternal(uri, httpMethod); } - @Override - public org.springframework.http.client.AsyncClientHttpRequest createAsyncRequest( - URI uri, HttpMethod httpMethod) { - - return createRequestInternal(uri, httpMethod); - } - - private org.springframework.mock.http.client.MockAsyncClientHttpRequest createRequestInternal( - URI uri, HttpMethod httpMethod) { - + private MockClientHttpRequest createRequestInternal(URI uri, HttpMethod httpMethod) { Assert.notNull(uri, "'uri' must not be null"); Assert.notNull(httpMethod, "'httpMethod' must not be null"); - return new org.springframework.mock.http.client.MockAsyncClientHttpRequest(httpMethod, uri) { + return new MockClientHttpRequest(httpMethod, uri) { @Override protected ClientHttpResponse executeInternal() throws IOException { diff --git a/spring-test/src/test/java/org/springframework/test/web/client/DefaultRequestExpectationTests.java b/spring-test/src/test/java/org/springframework/test/web/client/DefaultRequestExpectationTests.java index 2235119151..2c15775637 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/DefaultRequestExpectationTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/DefaultRequestExpectationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -23,10 +23,10 @@ import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpRequest; +import org.springframework.mock.http.client.MockClientHttpRequest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.springframework.http.HttpMethod.GET; import static org.springframework.http.HttpMethod.POST; import static org.springframework.test.web.client.ExpectedCount.once; import static org.springframework.test.web.client.ExpectedCount.twice; @@ -44,15 +44,15 @@ public class DefaultRequestExpectationTests { @Test public void match() throws Exception { RequestExpectation expectation = new DefaultRequestExpectation(once(), requestTo("/foo")); - expectation.match(createRequest(GET, "/foo")); + expectation.match(createRequest()); } @Test - public void matchWithFailedExpectation() throws Exception { + public void matchWithFailedExpectation() { RequestExpectation expectation = new DefaultRequestExpectation(once(), requestTo("/foo")); expectation.andExpect(method(POST)); assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> - expectation.match(createRequest(GET, "/foo"))) + expectation.match(createRequest())) .withMessageContaining("Unexpected HttpMethod expected: but was:"); } @@ -81,10 +81,9 @@ public class DefaultRequestExpectationTests { } - @SuppressWarnings("deprecation") - private ClientHttpRequest createRequest(HttpMethod method, String url) { + private ClientHttpRequest createRequest() { try { - return new org.springframework.mock.http.client.MockAsyncClientHttpRequest(method, new URI(url)); + return new MockClientHttpRequest(HttpMethod.GET, new URI("/foo")); } catch (URISyntaxException ex) { throw new IllegalStateException(ex); diff --git a/spring-test/src/test/java/org/springframework/test/web/client/UnorderedRequestExpectationManagerTests.java b/spring-test/src/test/java/org/springframework/test/web/client/UnorderedRequestExpectationManagerTests.java index f8f4cfa5b0..973a44df58 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/UnorderedRequestExpectationManagerTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/UnorderedRequestExpectationManagerTests.java @@ -23,6 +23,7 @@ import org.junit.jupiter.api.Test; import org.springframework.http.HttpMethod; import org.springframework.http.client.ClientHttpRequest; +import org.springframework.mock.http.client.MockClientHttpRequest; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -42,7 +43,7 @@ import static org.springframework.test.web.client.response.MockRestResponseCreat */ public class UnorderedRequestExpectationManagerTests { - private UnorderedRequestExpectationManager manager = new UnorderedRequestExpectationManager(); + private final UnorderedRequestExpectationManager manager = new UnorderedRequestExpectationManager(); @Test @@ -57,7 +58,7 @@ public class UnorderedRequestExpectationManagerTests { } @Test - public void zeroExpectedRequests() throws Exception { + public void zeroExpectedRequests() { this.manager.verify(); } @@ -108,19 +109,18 @@ public class UnorderedRequestExpectationManagerTests { this.manager.validateRequest(createRequest(GET, "/bar")); this.manager.validateRequest(createRequest(GET, "/foo")); this.manager.validateRequest(createRequest(GET, "/foo")); - assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> - this.manager.verify()) - .withMessageContaining("3 request(s) executed:\n" + - "GET /bar\n" + - "GET /foo\n" + - "GET /foo\n"); + assertThatExceptionOfType(AssertionError.class) + .isThrownBy(this.manager::verify) + .withMessageContaining("3 request(s) executed:\n" + + "GET /bar\n" + + "GET /foo\n" + + "GET /foo\n"); } - @SuppressWarnings("deprecation") private ClientHttpRequest createRequest(HttpMethod method, String url) { try { - return new org.springframework.mock.http.client.MockAsyncClientHttpRequest(method, new URI(url)); + return new MockClientHttpRequest(method, new URI(url)); } catch (URISyntaxException ex) { throw new IllegalStateException(ex); diff --git a/spring-test/src/test/java/org/springframework/test/web/client/samples/MockMvcClientHttpRequestFactoryTests.java b/spring-test/src/test/java/org/springframework/test/web/client/samples/MockMvcClientHttpRequestFactoryTests.java index 20262f0968..fc444a423f 100644 --- a/spring-test/src/test/java/org/springframework/test/web/client/samples/MockMvcClientHttpRequestFactoryTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/client/samples/MockMvcClientHttpRequestFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -23,7 +23,6 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -31,7 +30,6 @@ import org.springframework.test.context.web.WebAppConfiguration; import org.springframework.test.web.client.MockMvcClientHttpRequestFactory; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; -import org.springframework.util.concurrent.ListenableFuture; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; @@ -68,21 +66,12 @@ public class MockMvcClientHttpRequestFactoryTests { } @Test - public void test() throws Exception { + public void test() { RestTemplate template = new RestTemplate(new MockMvcClientHttpRequestFactory(this.mockMvc)); String result = template.getForObject("/foo", String.class); assertThat(result).isEqualTo("bar"); } - @Test - @SuppressWarnings("deprecation") - public void testAsyncTemplate() throws Exception { - org.springframework.web.client.AsyncRestTemplate template = new org.springframework.web.client.AsyncRestTemplate( - new MockMvcClientHttpRequestFactory(this.mockMvc)); - ListenableFuture> entity = template.getForEntity("/foo", String.class); - assertThat(entity.get().getBody()).isEqualTo("bar"); - } - @EnableWebMvc @Configuration diff --git a/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleAsyncTests.java b/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleAsyncTests.java deleted file mode 100644 index 975c46d384..0000000000 --- a/spring-test/src/test/java/org/springframework/test/web/client/samples/SampleAsyncTests.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2002-2019 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.test.web.client.samples; - -import org.junit.jupiter.api.Test; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.test.web.Person; -import org.springframework.test.web.client.MockRestServiceServer; -import org.springframework.util.concurrent.ListenableFuture; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.springframework.test.web.client.ExpectedCount.manyTimes; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.method; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess; - -/** - * Examples to demonstrate writing client-side REST tests with Spring MVC Test. - * While the tests in this class invoke the RestTemplate directly, in actual - * tests the RestTemplate may likely be invoked indirectly, i.e. through client - * code. - * - * @author Rossen Stoyanchev - * @since 4.1 - */ -@SuppressWarnings("deprecation") -public class SampleAsyncTests { - - private final org.springframework.web.client.AsyncRestTemplate restTemplate = new org.springframework.web.client.AsyncRestTemplate(); - - private final MockRestServiceServer mockServer = MockRestServiceServer.createServer(this.restTemplate); - - - @Test - public void performGet() throws Exception { - - String responseBody = "{\"name\" : \"Ludwig van Beethoven\", \"someDouble\" : \"1.6035\"}"; - - this.mockServer.expect(requestTo("/composers/42")).andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); - - @SuppressWarnings("unused") - ListenableFuture> ludwig = - this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); - - // We are only validating the request. The response is mocked out. - // person.getName().equals("Ludwig van Beethoven") - // person.getDouble().equals(1.6035) - - this.mockServer.verify(); - } - - @Test - public void performGetManyTimes() throws Exception { - - String responseBody = "{\"name\" : \"Ludwig van Beethoven\", \"someDouble\" : \"1.6035\"}"; - - this.mockServer.expect(manyTimes(), requestTo("/composers/42")).andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); - - @SuppressWarnings("unused") - ListenableFuture> ludwig = - this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); - - // We are only validating the request. The response is mocked out. - // person.getName().equals("Ludwig van Beethoven") - // person.getDouble().equals(1.6035) - - this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); - this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); - this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); - this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); - - this.mockServer.verify(); - } - - @Test - public void performGetWithResponseBodyFromFile() throws Exception { - - Resource responseBody = new ClassPathResource("ludwig.json", this.getClass()); - - this.mockServer.expect(requestTo("/composers/42")).andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess(responseBody, MediaType.APPLICATION_JSON)); - - @SuppressWarnings("unused") - ListenableFuture> ludwig = - this.restTemplate.getForEntity("/composers/{id}", Person.class, 42); - - // hotel.getId() == 42 - // hotel.getName().equals("Holiday Inn") - - this.mockServer.verify(); - } - - @Test - public void verify() { - - this.mockServer.expect(requestTo("/number")).andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess("1", MediaType.TEXT_PLAIN)); - - this.mockServer.expect(requestTo("/number")).andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess("2", MediaType.TEXT_PLAIN)); - - this.mockServer.expect(requestTo("/number")).andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess("4", MediaType.TEXT_PLAIN)); - - this.mockServer.expect(requestTo("/number")).andExpect(method(HttpMethod.GET)) - .andRespond(withSuccess("8", MediaType.TEXT_PLAIN)); - - @SuppressWarnings("unused") - ListenableFuture> result = this.restTemplate.getForEntity("/number", String.class); - // result == "1" - - result = this.restTemplate.getForEntity("/number", String.class); - // result == "2" - - try { - this.mockServer.verify(); - } - catch (AssertionError error) { - assertThat(error.getMessage().contains("2 unsatisfied expectation(s)")).as(error.getMessage()).isTrue(); - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/AbstractAsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/AbstractAsyncClientHttpRequest.java deleted file mode 100644 index 37b09134d9..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/AbstractAsyncClientHttpRequest.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; -import java.io.OutputStream; - -import org.springframework.http.HttpHeaders; -import org.springframework.util.Assert; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * Abstract base for {@link AsyncClientHttpRequest} that makes sure that headers and body - * are not written multiple times. - * - * @author Arjen Poutsma - * @since 4.0 - * @deprecated as of Spring 5.0, in favor of {@link org.springframework.http.client.reactive.AbstractClientHttpRequest} - */ -@Deprecated -abstract class AbstractAsyncClientHttpRequest implements AsyncClientHttpRequest { - - private final HttpHeaders headers = new HttpHeaders(); - - private boolean executed = false; - - - @Override - public final HttpHeaders getHeaders() { - return (this.executed ? HttpHeaders.readOnlyHttpHeaders(this.headers) : this.headers); - } - - @Override - public final OutputStream getBody() throws IOException { - assertNotExecuted(); - return getBodyInternal(this.headers); - } - - @Override - public ListenableFuture executeAsync() throws IOException { - assertNotExecuted(); - ListenableFuture result = executeInternal(this.headers); - this.executed = true; - return result; - } - - /** - * Asserts that this request has not been {@linkplain #executeAsync() executed} yet. - * @throws IllegalStateException if this request has been executed - */ - protected void assertNotExecuted() { - Assert.state(!this.executed, "ClientHttpRequest already executed"); - } - - - /** - * Abstract template method that returns the body. - * @param headers the HTTP headers - * @return the body output stream - */ - protected abstract OutputStream getBodyInternal(HttpHeaders headers) throws IOException; - - /** - * Abstract template method that writes the given headers and content to the HTTP request. - * @param headers the HTTP headers - * @return the response object for the executed request - */ - protected abstract ListenableFuture executeInternal(HttpHeaders headers) - throws IOException; - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/AbstractBufferingAsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/AbstractBufferingAsyncClientHttpRequest.java deleted file mode 100644 index f5c9aafe0e..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/AbstractBufferingAsyncClientHttpRequest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; - -import org.springframework.http.HttpHeaders; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * Base implementation of {@link AsyncClientHttpRequest} that buffers output - * in a byte array before sending it over the wire. - * - * @author Arjen Poutsma - * @since 4.0 - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -abstract class AbstractBufferingAsyncClientHttpRequest extends AbstractAsyncClientHttpRequest { - - private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream(1024); - - - @Override - protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException { - return this.bufferedOutput; - } - - @Override - protected ListenableFuture executeInternal(HttpHeaders headers) throws IOException { - byte[] bytes = this.bufferedOutput.toByteArray(); - if (headers.getContentLength() < 0) { - headers.setContentLength(bytes.length); - } - ListenableFuture result = executeInternal(headers, bytes); - this.bufferedOutput = new ByteArrayOutputStream(0); - return result; - } - - /** - * Abstract template method that writes the given headers and content to the HTTP request. - * @param headers the HTTP headers - * @param bufferedOutput the body content - * @return the response object for the executed request - */ - protected abstract ListenableFuture executeInternal( - HttpHeaders headers, byte[] bufferedOutput) throws IOException; - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequest.java deleted file mode 100644 index 39f3c83ae8..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequest.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; - -import org.springframework.http.HttpOutputMessage; -import org.springframework.http.HttpRequest; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * Represents a client-side asynchronous HTTP request. Created via an - * implementation of the {@link AsyncClientHttpRequestFactory}. - * - *

A {@code AsyncHttpRequest} can be {@linkplain #executeAsync() executed}, - * getting a future {@link ClientHttpResponse} which can be read from. - * - * @author Arjen Poutsma - * @since 4.0 - * @see AsyncClientHttpRequestFactory#createAsyncRequest - * @deprecated as of Spring 5.0, in favor of {@link org.springframework.web.reactive.function.client.ClientRequest} - */ -@Deprecated -public interface AsyncClientHttpRequest extends HttpRequest, HttpOutputMessage { - - /** - * Execute this request asynchronously, resulting in a Future handle. - * {@link ClientHttpResponse} that can be read. - * @return the future response result of the execution - * @throws java.io.IOException in case of I/O errors - */ - ListenableFuture executeAsync() throws IOException; - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestExecution.java b/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestExecution.java deleted file mode 100644 index 97ecb225cb..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestExecution.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; - -import org.springframework.http.HttpRequest; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * Represents the context of a client-side HTTP request execution. - * - *

Used to invoke the next interceptor in the interceptor chain, or - - * if the calling interceptor is last - execute the request itself. - * - * @author Jakub Narloch - * @author Rossen Stoyanchev - * @since 4.3 - * @see AsyncClientHttpRequestInterceptor - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction} - */ -@Deprecated -public interface AsyncClientHttpRequestExecution { - - /** - * Resume the request execution by invoking the next interceptor in the chain - * or executing the request to the remote service. - * @param request the HTTP request, containing the HTTP method and headers - * @param body the body of the request - * @return a corresponding future handle - * @throws IOException in case of I/O errors - */ - ListenableFuture executeAsync(HttpRequest request, byte[] body) throws IOException; - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestFactory.java deleted file mode 100644 index 509d1da713..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestFactory.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; -import java.net.URI; - -import org.springframework.http.HttpMethod; - -/** - * Factory for {@link AsyncClientHttpRequest} objects. - * Requests are created by the {@link #createAsyncRequest(URI, HttpMethod)} method. - * - * @author Arjen Poutsma - * @since 4.0 - * @deprecated as of Spring 5.0, in favor of {@link org.springframework.http.client.reactive.ClientHttpConnector} - */ -@Deprecated -public interface AsyncClientHttpRequestFactory { - - /** - * Create a new asynchronous {@link AsyncClientHttpRequest} for the specified URI - * and HTTP method. - *

The returned request can be written to, and then executed by calling - * {@link AsyncClientHttpRequest#executeAsync()}. - * @param uri the URI to create a request for - * @param httpMethod the HTTP method to execute - * @return the created request - * @throws IOException in case of I/O errors - */ - AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException; - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestInterceptor.java b/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestInterceptor.java deleted file mode 100644 index 34ed8c024e..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/AsyncClientHttpRequestInterceptor.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; - -import org.springframework.http.HttpRequest; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * Intercepts client-side HTTP requests. Implementations of this interface can be - * {@linkplain org.springframework.web.client.AsyncRestTemplate#setInterceptors registered} - * with the {@link org.springframework.web.client.AsyncRestTemplate} as to modify - * the outgoing {@link HttpRequest} and/or register to modify the incoming - * {@link ClientHttpResponse} with help of a - * {@link org.springframework.util.concurrent.ListenableFutureAdapter}. - * - *

The main entry point for interceptors is {@link #intercept}. - * - * @author Jakub Narloch - * @author Rossen Stoyanchev - * @since 4.3 - * @see org.springframework.web.client.AsyncRestTemplate - * @see org.springframework.http.client.support.InterceptingAsyncHttpAccessor - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction} - */ -@Deprecated -public interface AsyncClientHttpRequestInterceptor { - - /** - * Intercept the given request, and return a response future. The given - * {@link AsyncClientHttpRequestExecution} allows the interceptor to pass on - * the request to the next entity in the chain. - *

An implementation might follow this pattern: - *

    - *
  1. Examine the {@linkplain HttpRequest request} and body
  2. - *
  3. Optionally {@linkplain org.springframework.http.client.support.HttpRequestWrapper - * wrap} the request to filter HTTP attributes.
  4. - *
  5. Optionally modify the body of the request.
  6. - *
  7. One of the following: - *
      - *
    • execute the request through {@link ClientHttpRequestExecution}
    • - *
    • don't execute the request to block the execution altogether
    • - *
    - *
  8. Optionally adapt the response to filter HTTP attributes with the help of - * {@link org.springframework.util.concurrent.ListenableFutureAdapter - * ListenableFutureAdapter}.
  9. - *
- * @param request the request, containing method, URI, and headers - * @param body the body of the request - * @param execution the request execution - * @return the response future - * @throws IOException in case of I/O errors - */ - ListenableFuture intercept(HttpRequest request, byte[] body, - AsyncClientHttpRequestExecution execution) throws IOException; - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequest.java deleted file mode 100644 index ca97edde0b..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequest.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; -import java.net.URI; -import java.util.concurrent.Future; - -import org.apache.http.HttpEntity; -import org.apache.http.HttpEntityEnclosingRequest; -import org.apache.http.HttpResponse; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.concurrent.FutureCallback; -import org.apache.http.nio.client.HttpAsyncClient; -import org.apache.http.nio.entity.NByteArrayEntity; -import org.apache.http.protocol.HttpContext; - -import org.springframework.http.HttpHeaders; -import org.springframework.util.concurrent.FailureCallback; -import org.springframework.util.concurrent.FutureAdapter; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.ListenableFutureCallback; -import org.springframework.util.concurrent.ListenableFutureCallbackRegistry; -import org.springframework.util.concurrent.SuccessCallback; - - -/** - * {@link ClientHttpRequest} implementation based on - * Apache HttpComponents HttpAsyncClient. - * - *

Created via the {@link HttpComponentsClientHttpRequestFactory}. - * - * @author Oleg Kalnichevski - * @author Arjen Poutsma - * @since 4.0 - * @see HttpComponentsClientHttpRequestFactory#createRequest - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.http.client.reactive.HttpComponentsClientHttpConnector} - */ -@Deprecated -final class HttpComponentsAsyncClientHttpRequest extends AbstractBufferingAsyncClientHttpRequest { - - private final HttpAsyncClient httpClient; - - private final HttpUriRequest httpRequest; - - private final HttpContext httpContext; - - - HttpComponentsAsyncClientHttpRequest(HttpAsyncClient client, HttpUriRequest request, HttpContext context) { - this.httpClient = client; - this.httpRequest = request; - this.httpContext = context; - } - - - @Override - public String getMethodValue() { - return this.httpRequest.getMethod(); - } - - @Override - public URI getURI() { - return this.httpRequest.getURI(); - } - - HttpContext getHttpContext() { - return this.httpContext; - } - - @Override - protected ListenableFuture executeInternal(HttpHeaders headers, byte[] bufferedOutput) - throws IOException { - - HttpComponentsClientHttpRequest.addHeaders(this.httpRequest, headers); - - if (this.httpRequest instanceof HttpEntityEnclosingRequest) { - HttpEntityEnclosingRequest entityEnclosingRequest = (HttpEntityEnclosingRequest) this.httpRequest; - HttpEntity requestEntity = new NByteArrayEntity(bufferedOutput); - entityEnclosingRequest.setEntity(requestEntity); - } - - HttpResponseFutureCallback callback = new HttpResponseFutureCallback(this.httpRequest); - Future futureResponse = this.httpClient.execute(this.httpRequest, this.httpContext, callback); - return new ClientHttpResponseFuture(futureResponse, callback); - } - - - private static class HttpResponseFutureCallback implements FutureCallback { - - private final HttpUriRequest request; - - private final ListenableFutureCallbackRegistry callbacks = - new ListenableFutureCallbackRegistry<>(); - - public HttpResponseFutureCallback(HttpUriRequest request) { - this.request = request; - } - - public void addCallback(ListenableFutureCallback callback) { - this.callbacks.addCallback(callback); - } - - public void addSuccessCallback(SuccessCallback callback) { - this.callbacks.addSuccessCallback(callback); - } - - public void addFailureCallback(FailureCallback callback) { - this.callbacks.addFailureCallback(callback); - } - - @Override - public void completed(HttpResponse result) { - this.callbacks.success(new HttpComponentsAsyncClientHttpResponse(result)); - } - - @Override - public void failed(Exception ex) { - this.callbacks.failure(ex); - } - - @Override - public void cancelled() { - this.request.abort(); - } - } - - - private static class ClientHttpResponseFuture extends FutureAdapter - implements ListenableFuture { - - private final HttpResponseFutureCallback callback; - - public ClientHttpResponseFuture(Future response, HttpResponseFutureCallback callback) { - super(response); - this.callback = callback; - } - - @Override - protected ClientHttpResponse adapt(HttpResponse response) { - return new HttpComponentsAsyncClientHttpResponse(response); - } - - @Override - public void addCallback(ListenableFutureCallback callback) { - this.callback.addCallback(callback); - } - - @Override - public void addCallback(SuccessCallback successCallback, - FailureCallback failureCallback) { - - this.callback.addSuccessCallback(successCallback); - this.callback.addFailureCallback(failureCallback); - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactory.java deleted file mode 100644 index 84bd07a159..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactory.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2002-2018 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.http.client; - -import java.io.Closeable; -import java.io.IOException; -import java.net.URI; - -import org.apache.http.client.HttpClient; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.Configurable; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; -import org.apache.http.impl.nio.client.HttpAsyncClients; -import org.apache.http.nio.client.HttpAsyncClient; -import org.apache.http.protocol.HttpContext; - -import org.springframework.beans.factory.InitializingBean; -import org.springframework.http.HttpMethod; -import org.springframework.util.Assert; - -/** - * Asynchronous extension of the {@link HttpComponentsClientHttpRequestFactory}. Uses - * Apache HttpComponents - * HttpAsyncClient 4.0 to create requests. - * - * @author Arjen Poutsma - * @author Stephane Nicoll - * @since 4.0 - * @see HttpAsyncClient - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.http.client.reactive.HttpComponentsClientHttpConnector} - */ -@Deprecated -public class HttpComponentsAsyncClientHttpRequestFactory extends HttpComponentsClientHttpRequestFactory - implements AsyncClientHttpRequestFactory, InitializingBean { - - private HttpAsyncClient asyncClient; - - - /** - * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} - * with a default {@link HttpAsyncClient} and {@link HttpClient}. - */ - public HttpComponentsAsyncClientHttpRequestFactory() { - super(); - this.asyncClient = HttpAsyncClients.createSystem(); - } - - /** - * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} - * with the given {@link HttpAsyncClient} instance and a default {@link HttpClient}. - * @param asyncClient the HttpAsyncClient instance to use for this request factory - * @since 4.3.10 - */ - public HttpComponentsAsyncClientHttpRequestFactory(HttpAsyncClient asyncClient) { - super(); - this.asyncClient = asyncClient; - } - - /** - * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} - * with the given {@link CloseableHttpAsyncClient} instance and a default {@link HttpClient}. - * @param asyncClient the CloseableHttpAsyncClient instance to use for this request factory - */ - public HttpComponentsAsyncClientHttpRequestFactory(CloseableHttpAsyncClient asyncClient) { - super(); - this.asyncClient = asyncClient; - } - - /** - * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} - * with the given {@link HttpClient} and {@link HttpAsyncClient} instances. - * @param httpClient the HttpClient instance to use for this request factory - * @param asyncClient the HttpAsyncClient instance to use for this request factory - * @since 4.3.10 - */ - public HttpComponentsAsyncClientHttpRequestFactory(HttpClient httpClient, HttpAsyncClient asyncClient) { - super(httpClient); - this.asyncClient = asyncClient; - } - - /** - * Create a new instance of the {@code HttpComponentsAsyncClientHttpRequestFactory} - * with the given {@link CloseableHttpClient} and {@link CloseableHttpAsyncClient} instances. - * @param httpClient the CloseableHttpClient instance to use for this request factory - * @param asyncClient the CloseableHttpAsyncClient instance to use for this request factory - */ - public HttpComponentsAsyncClientHttpRequestFactory( - CloseableHttpClient httpClient, CloseableHttpAsyncClient asyncClient) { - - super(httpClient); - this.asyncClient = asyncClient; - } - - - /** - * Set the {@code HttpAsyncClient} used for - * {@linkplain #createAsyncRequest(URI, HttpMethod) synchronous execution}. - * @since 4.3.10 - * @see #setHttpClient(HttpClient) - */ - public void setAsyncClient(HttpAsyncClient asyncClient) { - Assert.notNull(asyncClient, "HttpAsyncClient must not be null"); - this.asyncClient = asyncClient; - } - - /** - * Return the {@code HttpAsyncClient} used for - * {@linkplain #createAsyncRequest(URI, HttpMethod) synchronous execution}. - * @since 4.3.10 - * @see #getHttpClient() - */ - public HttpAsyncClient getAsyncClient() { - return this.asyncClient; - } - - /** - * Set the {@code CloseableHttpAsyncClient} used for - * {@linkplain #createAsyncRequest(URI, HttpMethod) asynchronous execution}. - * @deprecated as of 4.3.10, in favor of {@link #setAsyncClient(HttpAsyncClient)} - */ - @Deprecated - public void setHttpAsyncClient(CloseableHttpAsyncClient asyncClient) { - this.asyncClient = asyncClient; - } - - /** - * Return the {@code CloseableHttpAsyncClient} used for - * {@linkplain #createAsyncRequest(URI, HttpMethod) asynchronous execution}. - * @deprecated as of 4.3.10, in favor of {@link #getAsyncClient()} - */ - @Deprecated - public CloseableHttpAsyncClient getHttpAsyncClient() { - Assert.state(this.asyncClient instanceof CloseableHttpAsyncClient, - "No CloseableHttpAsyncClient - use getAsyncClient() instead"); - return (CloseableHttpAsyncClient) this.asyncClient; - } - - - @Override - public void afterPropertiesSet() { - startAsyncClient(); - } - - private HttpAsyncClient startAsyncClient() { - HttpAsyncClient client = getAsyncClient(); - if (client instanceof CloseableHttpAsyncClient) { - @SuppressWarnings("resource") - CloseableHttpAsyncClient closeableAsyncClient = (CloseableHttpAsyncClient) client; - if (!closeableAsyncClient.isRunning()) { - closeableAsyncClient.start(); - } - } - return client; - } - - @Override - public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException { - HttpAsyncClient client = startAsyncClient(); - - HttpUriRequest httpRequest = createHttpUriRequest(httpMethod, uri); - postProcessHttpRequest(httpRequest); - HttpContext context = createHttpContext(httpMethod, uri); - if (context == null) { - context = HttpClientContext.create(); - } - - // Request configuration not set in the context - if (context.getAttribute(HttpClientContext.REQUEST_CONFIG) == null) { - // Use request configuration given by the user, when available - RequestConfig config = null; - if (httpRequest instanceof Configurable) { - config = ((Configurable) httpRequest).getConfig(); - } - if (config == null) { - config = createRequestConfig(client); - } - if (config != null) { - context.setAttribute(HttpClientContext.REQUEST_CONFIG, config); - } - } - - return new HttpComponentsAsyncClientHttpRequest(client, httpRequest, context); - } - - @Override - public void destroy() throws Exception { - try { - super.destroy(); - } - finally { - HttpAsyncClient asyncClient = getAsyncClient(); - if (asyncClient instanceof Closeable) { - ((Closeable) asyncClient).close(); - } - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpResponse.java deleted file mode 100644 index 54297db860..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/HttpComponentsAsyncClientHttpResponse.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; -import java.io.InputStream; - -import org.apache.http.Header; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; - -import org.springframework.http.HttpHeaders; -import org.springframework.lang.Nullable; -import org.springframework.util.StreamUtils; - -/** - * {@link ClientHttpResponse} implementation based on - * Apache HttpComponents HttpAsyncClient. - * - *

Created via the {@link HttpComponentsAsyncClientHttpRequest}. - * - * @author Oleg Kalnichevski - * @author Arjen Poutsma - * @since 4.0 - * @see HttpComponentsAsyncClientHttpRequest#executeAsync() - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.http.client.reactive.HttpComponentsClientHttpConnector} - */ -@Deprecated -final class HttpComponentsAsyncClientHttpResponse extends AbstractClientHttpResponse { - - private final HttpResponse httpResponse; - - @Nullable - private HttpHeaders headers; - - - HttpComponentsAsyncClientHttpResponse(HttpResponse httpResponse) { - this.httpResponse = httpResponse; - } - - - @Override - public int getRawStatusCode() throws IOException { - return this.httpResponse.getStatusLine().getStatusCode(); - } - - @Override - public String getStatusText() throws IOException { - return this.httpResponse.getStatusLine().getReasonPhrase(); - } - - @Override - public HttpHeaders getHeaders() { - if (this.headers == null) { - this.headers = new HttpHeaders(); - for (Header header : this.httpResponse.getAllHeaders()) { - this.headers.add(header.getName(), header.getValue()); - } - } - return this.headers; - } - - @Override - public InputStream getBody() throws IOException { - HttpEntity entity = this.httpResponse.getEntity(); - return (entity != null ? entity.getContent() : StreamUtils.emptyInput()); - } - - @Override - public void close() { - // HTTP responses returned by async HTTP client are not bound to an - // active connection and do not have to deallocate any resources... - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/InterceptingAsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/InterceptingAsyncClientHttpRequest.java deleted file mode 100644 index 4dd835f294..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/InterceptingAsyncClientHttpRequest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2002-2018 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.http.client; - -import java.io.IOException; -import java.net.URI; -import java.util.Iterator; -import java.util.List; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpRequest; -import org.springframework.util.Assert; -import org.springframework.util.StreamUtils; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * An {@link AsyncClientHttpRequest} wrapper that enriches it proceeds the actual - * request execution with calling the registered interceptors. - * - * @author Jakub Narloch - * @author Rossen Stoyanchev - * @see InterceptingAsyncClientHttpRequestFactory - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -class InterceptingAsyncClientHttpRequest extends AbstractBufferingAsyncClientHttpRequest { - - private AsyncClientHttpRequestFactory requestFactory; - - private List interceptors; - - private URI uri; - - private HttpMethod httpMethod; - - - /** - * Create new instance of {@link InterceptingAsyncClientHttpRequest}. - * @param requestFactory the async request factory - * @param interceptors the list of interceptors - * @param uri the request URI - * @param httpMethod the HTTP method - */ - public InterceptingAsyncClientHttpRequest(AsyncClientHttpRequestFactory requestFactory, - List interceptors, URI uri, HttpMethod httpMethod) { - - this.requestFactory = requestFactory; - this.interceptors = interceptors; - this.uri = uri; - this.httpMethod = httpMethod; - } - - - @Override - protected ListenableFuture executeInternal(HttpHeaders headers, byte[] body) - throws IOException { - - return new AsyncRequestExecution().executeAsync(this, body); - } - - @Override - public HttpMethod getMethod() { - return this.httpMethod; - } - - @Override - public String getMethodValue() { - return this.httpMethod.name(); - } - - @Override - public URI getURI() { - return this.uri; - } - - - private class AsyncRequestExecution implements AsyncClientHttpRequestExecution { - - private Iterator iterator; - - public AsyncRequestExecution() { - this.iterator = interceptors.iterator(); - } - - @Override - public ListenableFuture executeAsync(HttpRequest request, byte[] body) - throws IOException { - - if (this.iterator.hasNext()) { - AsyncClientHttpRequestInterceptor interceptor = this.iterator.next(); - return interceptor.intercept(request, body, this); - } - else { - URI uri = request.getURI(); - HttpMethod method = request.getMethod(); - HttpHeaders headers = request.getHeaders(); - - Assert.state(method != null, "No standard HTTP method"); - AsyncClientHttpRequest delegate = requestFactory.createAsyncRequest(uri, method); - delegate.getHeaders().putAll(headers); - if (body.length > 0) { - StreamUtils.copy(body, delegate.getBody()); - } - - return delegate.executeAsync(); - } - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/InterceptingAsyncClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/InterceptingAsyncClientHttpRequestFactory.java deleted file mode 100644 index 9721e46cc2..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/InterceptingAsyncClientHttpRequestFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2002-2018 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.http.client; - -import java.net.URI; -import java.util.Collections; -import java.util.List; - -import org.springframework.http.HttpMethod; -import org.springframework.lang.Nullable; - -/** - * Wrapper for a {@link AsyncClientHttpRequestFactory} that has support for - * {@link AsyncClientHttpRequestInterceptor AsyncClientHttpRequestInterceptors}. - * - * @author Jakub Narloch - * @since 4.3 - * @see InterceptingAsyncClientHttpRequest - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -public class InterceptingAsyncClientHttpRequestFactory implements AsyncClientHttpRequestFactory { - - private AsyncClientHttpRequestFactory delegate; - - private List interceptors; - - - /** - * Create new instance of {@link InterceptingAsyncClientHttpRequestFactory} - * with delegated request factory and list of interceptors. - * @param delegate the request factory to delegate to - * @param interceptors the list of interceptors to use - */ - public InterceptingAsyncClientHttpRequestFactory(AsyncClientHttpRequestFactory delegate, - @Nullable List interceptors) { - - this.delegate = delegate; - this.interceptors = (interceptors != null ? interceptors : Collections.emptyList()); - } - - - @Override - public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod method) { - return new InterceptingAsyncClientHttpRequest(this.delegate, this.interceptors, uri, method); - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequest.java deleted file mode 100644 index c4c7d6f37d..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequest.java +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright 2002-2018 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.http.client; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.URI; -import java.util.concurrent.ExecutionException; - -import io.netty.bootstrap.Bootstrap; -import io.netty.buffer.ByteBufOutputStream; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.DefaultFullHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.HttpVersion; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.SettableListenableFuture; - -/** - * {@link ClientHttpRequest} implementation based on Netty 4. - * - *

Created via the {@link Netty4ClientHttpRequestFactory}. - * - * @author Arjen Poutsma - * @author Rossen Stoyanchev - * @author Brian Clozel - * @since 4.1.2 - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.http.client.reactive.ReactorClientHttpConnector} - */ -@Deprecated -class Netty4ClientHttpRequest extends AbstractAsyncClientHttpRequest implements ClientHttpRequest { - - private final Bootstrap bootstrap; - - private final URI uri; - - private final HttpMethod method; - - private final ByteBufOutputStream body; - - - public Netty4ClientHttpRequest(Bootstrap bootstrap, URI uri, HttpMethod method) { - this.bootstrap = bootstrap; - this.uri = uri; - this.method = method; - this.body = new ByteBufOutputStream(Unpooled.buffer(1024)); - } - - - @Override - public HttpMethod getMethod() { - return this.method; - } - - @Override - public String getMethodValue() { - return this.method.name(); - } - - @Override - public URI getURI() { - return this.uri; - } - - @Override - public ClientHttpResponse execute() throws IOException { - try { - return executeAsync().get(); - } - catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new IOException("Interrupted during request execution", ex); - } - catch (ExecutionException ex) { - if (ex.getCause() instanceof IOException) { - throw (IOException) ex.getCause(); - } - else { - throw new IOException(ex.getMessage(), ex.getCause()); - } - } - } - - @Override - protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException { - return this.body; - } - - @Override - protected ListenableFuture executeInternal(final HttpHeaders headers) throws IOException { - final SettableListenableFuture responseFuture = new SettableListenableFuture<>(); - - ChannelFutureListener connectionListener = future -> { - if (future.isSuccess()) { - Channel channel = future.channel(); - channel.pipeline().addLast(new RequestExecuteHandler(responseFuture)); - FullHttpRequest nettyRequest = createFullHttpRequest(headers); - channel.writeAndFlush(nettyRequest); - } - else { - responseFuture.setException(future.cause()); - } - }; - - this.bootstrap.connect(this.uri.getHost(), getPort(this.uri)).addListener(connectionListener); - return responseFuture; - } - - private FullHttpRequest createFullHttpRequest(HttpHeaders headers) { - io.netty.handler.codec.http.HttpMethod nettyMethod = - io.netty.handler.codec.http.HttpMethod.valueOf(this.method.name()); - - String authority = this.uri.getRawAuthority(); - String path = this.uri.toString().substring(this.uri.toString().indexOf(authority) + authority.length()); - FullHttpRequest nettyRequest = new DefaultFullHttpRequest( - HttpVersion.HTTP_1_1, nettyMethod, path, this.body.buffer()); - - nettyRequest.headers().set(HttpHeaders.HOST, this.uri.getHost() + ":" + getPort(this.uri)); - nettyRequest.headers().set(HttpHeaders.CONNECTION, "close"); - headers.forEach((headerName, headerValues) -> nettyRequest.headers().add(headerName, headerValues)); - if (!nettyRequest.headers().contains(HttpHeaders.CONTENT_LENGTH) && this.body.buffer().readableBytes() > 0) { - nettyRequest.headers().set(HttpHeaders.CONTENT_LENGTH, this.body.buffer().readableBytes()); - } - - return nettyRequest; - } - - private static int getPort(URI uri) { - int port = uri.getPort(); - if (port == -1) { - if ("http".equalsIgnoreCase(uri.getScheme())) { - port = 80; - } - else if ("https".equalsIgnoreCase(uri.getScheme())) { - port = 443; - } - } - return port; - } - - - /** - * A SimpleChannelInboundHandler to update the given SettableListenableFuture. - */ - private static class RequestExecuteHandler extends SimpleChannelInboundHandler { - - private final SettableListenableFuture responseFuture; - - public RequestExecuteHandler(SettableListenableFuture responseFuture) { - this.responseFuture = responseFuture; - } - - @Override - protected void channelRead0(ChannelHandlerContext context, FullHttpResponse response) throws Exception { - this.responseFuture.set(new Netty4ClientHttpResponse(context, response)); - } - - @Override - public void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception { - this.responseFuture.setException(cause); - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequestFactory.java deleted file mode 100644 index bc0c83472f..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpRequestFactory.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2002-2018 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.http.client; - -import java.io.IOException; -import java.net.URI; -import java.util.concurrent.TimeUnit; - -import javax.net.ssl.SSLException; - -import io.netty.bootstrap.Bootstrap; -import io.netty.channel.ChannelConfig; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.SocketChannelConfig; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.SslContextBuilder; -import io.netty.handler.timeout.ReadTimeoutHandler; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.http.HttpMethod; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * {@link org.springframework.http.client.ClientHttpRequestFactory} implementation - * that uses Netty 4 to create requests. - * - *

Allows to use a pre-configured {@link EventLoopGroup} instance: useful for - * sharing across multiple clients. - * - *

Note that this implementation consistently closes the HTTP connection on each - * request. - * - * @author Arjen Poutsma - * @author Rossen Stoyanchev - * @author Brian Clozel - * @author Mark Paluch - * @since 4.1.2 - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.http.client.reactive.ReactorClientHttpConnector} - */ -@Deprecated -public class Netty4ClientHttpRequestFactory implements ClientHttpRequestFactory, - AsyncClientHttpRequestFactory, InitializingBean, DisposableBean { - - /** - * The default maximum response size. - * @see #setMaxResponseSize(int) - */ - public static final int DEFAULT_MAX_RESPONSE_SIZE = 1024 * 1024 * 10; - - - private final EventLoopGroup eventLoopGroup; - - private final boolean defaultEventLoopGroup; - - private int maxResponseSize = DEFAULT_MAX_RESPONSE_SIZE; - - @Nullable - private SslContext sslContext; - - private int connectTimeout = -1; - - private int readTimeout = -1; - - @Nullable - private volatile Bootstrap bootstrap; - - - /** - * Create a new {@code Netty4ClientHttpRequestFactory} with a default - * {@link NioEventLoopGroup}. - */ - public Netty4ClientHttpRequestFactory() { - int ioWorkerCount = Runtime.getRuntime().availableProcessors() * 2; - this.eventLoopGroup = new NioEventLoopGroup(ioWorkerCount); - this.defaultEventLoopGroup = true; - } - - /** - * Create a new {@code Netty4ClientHttpRequestFactory} with the given - * {@link EventLoopGroup}. - *

NOTE: the given group will not be - * {@linkplain EventLoopGroup#shutdownGracefully() shutdown} by this factory; - * doing so becomes the responsibility of the caller. - */ - public Netty4ClientHttpRequestFactory(EventLoopGroup eventLoopGroup) { - Assert.notNull(eventLoopGroup, "EventLoopGroup must not be null"); - this.eventLoopGroup = eventLoopGroup; - this.defaultEventLoopGroup = false; - } - - - /** - * Set the default maximum response size. - *

By default this is set to {@link #DEFAULT_MAX_RESPONSE_SIZE}. - * @since 4.1.5 - * @see HttpObjectAggregator#HttpObjectAggregator(int) - */ - public void setMaxResponseSize(int maxResponseSize) { - this.maxResponseSize = maxResponseSize; - } - - /** - * Set the SSL context. When configured it is used to create and insert an - * {@link io.netty.handler.ssl.SslHandler} in the channel pipeline. - *

A default client SslContext is configured if none has been provided. - */ - public void setSslContext(SslContext sslContext) { - this.sslContext = sslContext; - } - - /** - * Set the underlying connect timeout (in milliseconds). - * A timeout value of 0 specifies an infinite timeout. - * @see ChannelConfig#setConnectTimeoutMillis(int) - */ - public void setConnectTimeout(int connectTimeout) { - this.connectTimeout = connectTimeout; - } - - /** - * Set the underlying URLConnection's read timeout (in milliseconds). - * A timeout value of 0 specifies an infinite timeout. - * @see ReadTimeoutHandler - */ - public void setReadTimeout(int readTimeout) { - this.readTimeout = readTimeout; - } - - - @Override - public void afterPropertiesSet() { - if (this.sslContext == null) { - this.sslContext = getDefaultClientSslContext(); - } - } - - private SslContext getDefaultClientSslContext() { - try { - return SslContextBuilder.forClient().build(); - } - catch (SSLException ex) { - throw new IllegalStateException("Could not create default client SslContext", ex); - } - } - - - @Override - public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { - return createRequestInternal(uri, httpMethod); - } - - @Override - public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException { - return createRequestInternal(uri, httpMethod); - } - - private Netty4ClientHttpRequest createRequestInternal(URI uri, HttpMethod httpMethod) { - return new Netty4ClientHttpRequest(getBootstrap(uri), uri, httpMethod); - } - - private Bootstrap getBootstrap(URI uri) { - boolean isSecure = (uri.getPort() == 443 || "https".equalsIgnoreCase(uri.getScheme())); - if (isSecure) { - return buildBootstrap(uri, true); - } - else { - Bootstrap bootstrap = this.bootstrap; - if (bootstrap == null) { - bootstrap = buildBootstrap(uri, false); - this.bootstrap = bootstrap; - } - return bootstrap; - } - } - - private Bootstrap buildBootstrap(URI uri, boolean isSecure) { - Bootstrap bootstrap = new Bootstrap(); - bootstrap.group(this.eventLoopGroup).channel(NioSocketChannel.class) - .handler(new ChannelInitializer() { - @Override - protected void initChannel(SocketChannel channel) throws Exception { - configureChannel(channel.config()); - ChannelPipeline pipeline = channel.pipeline(); - if (isSecure) { - Assert.notNull(sslContext, "sslContext should not be null"); - pipeline.addLast(sslContext.newHandler(channel.alloc(), uri.getHost(), uri.getPort())); - } - pipeline.addLast(new HttpClientCodec()); - pipeline.addLast(new HttpObjectAggregator(maxResponseSize)); - if (readTimeout > 0) { - pipeline.addLast(new ReadTimeoutHandler(readTimeout, - TimeUnit.MILLISECONDS)); - } - } - }); - return bootstrap; - } - - /** - * Template method for changing properties on the given {@link SocketChannelConfig}. - *

The default implementation sets the connect timeout based on the set property. - * @param config the channel configuration - */ - protected void configureChannel(SocketChannelConfig config) { - if (this.connectTimeout >= 0) { - config.setConnectTimeoutMillis(this.connectTimeout); - } - } - - - @Override - public void destroy() throws InterruptedException { - if (this.defaultEventLoopGroup) { - // Clean up the EventLoopGroup if we created it in the constructor - this.eventLoopGroup.shutdownGracefully().sync(); - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpResponse.java b/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpResponse.java deleted file mode 100644 index 6ac0de0a19..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/Netty4ClientHttpResponse.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Map; - -import io.netty.buffer.ByteBufInputStream; -import io.netty.channel.ChannelHandlerContext; -import io.netty.handler.codec.http.FullHttpResponse; - -import org.springframework.http.HttpHeaders; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * {@link ClientHttpResponse} implementation based on Netty 4. - * - * @author Arjen Poutsma - * @since 4.1.2 - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.http.client.reactive.ReactorClientHttpConnector} - */ -@Deprecated -class Netty4ClientHttpResponse extends AbstractClientHttpResponse { - - private final ChannelHandlerContext context; - - private final FullHttpResponse nettyResponse; - - private final ByteBufInputStream body; - - @Nullable - private volatile HttpHeaders headers; - - - public Netty4ClientHttpResponse(ChannelHandlerContext context, FullHttpResponse nettyResponse) { - Assert.notNull(context, "ChannelHandlerContext must not be null"); - Assert.notNull(nettyResponse, "FullHttpResponse must not be null"); - this.context = context; - this.nettyResponse = nettyResponse; - this.body = new ByteBufInputStream(this.nettyResponse.content()); - this.nettyResponse.retain(); - } - - - @Override - public int getRawStatusCode() throws IOException { - return this.nettyResponse.getStatus().code(); - } - - @Override - public String getStatusText() throws IOException { - return this.nettyResponse.getStatus().reasonPhrase(); - } - - @Override - public HttpHeaders getHeaders() { - HttpHeaders headers = this.headers; - if (headers == null) { - headers = new HttpHeaders(); - for (Map.Entry entry : this.nettyResponse.headers()) { - headers.add(entry.getKey(), entry.getValue()); - } - this.headers = headers; - } - return headers; - } - - @Override - public InputStream getBody() throws IOException { - return this.body; - } - - @Override - public void close() { - this.nettyResponse.release(); - this.context.close(); - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/OkHttp3AsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/OkHttp3AsyncClientHttpRequest.java deleted file mode 100644 index ee8d2eb233..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/OkHttp3AsyncClientHttpRequest.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client; - -import java.io.IOException; -import java.net.URI; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; - -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.SettableListenableFuture; - -/** - * {@link AsyncClientHttpRequest} implementation based on OkHttp 3.x. - * - *

Created via the {@link OkHttp3ClientHttpRequestFactory}. - * - * @author Luciano Leggieri - * @author Arjen Poutsma - * @author Roy Clarkson - * @since 4.3 - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -class OkHttp3AsyncClientHttpRequest extends AbstractBufferingAsyncClientHttpRequest { - - private final OkHttpClient client; - - private final URI uri; - - private final HttpMethod method; - - - public OkHttp3AsyncClientHttpRequest(OkHttpClient client, URI uri, HttpMethod method) { - this.client = client; - this.uri = uri; - this.method = method; - } - - - @Override - public HttpMethod getMethod() { - return this.method; - } - - @Override - public String getMethodValue() { - return this.method.name(); - } - - @Override - public URI getURI() { - return this.uri; - } - - @Override - protected ListenableFuture executeInternal(HttpHeaders headers, byte[] content) - throws IOException { - - Request request = OkHttp3ClientHttpRequestFactory.buildRequest(headers, content, this.uri, this.method); - return new OkHttpListenableFuture(this.client.newCall(request)); - } - - - private static class OkHttpListenableFuture extends SettableListenableFuture { - - private final Call call; - - public OkHttpListenableFuture(Call call) { - this.call = call; - this.call.enqueue(new Callback() { - @Override - public void onResponse(Call call, Response response) { - set(new OkHttp3ClientHttpResponse(response)); - } - @Override - public void onFailure(Call call, IOException ex) { - setException(ex); - } - }); - } - - @Override - protected void interruptTask() { - this.call.cancel(); - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpRequestFactory.java index f23febf88d..e81bbe61a4 100644 --- a/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpRequestFactory.java +++ b/spring-web/src/main/java/org/springframework/http/client/OkHttp3ClientHttpRequestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -42,9 +42,7 @@ import org.springframework.util.StringUtils; * @author Roy Clarkson * @since 4.3 */ -@SuppressWarnings("deprecation") -public class OkHttp3ClientHttpRequestFactory - implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory, DisposableBean { +public class OkHttp3ClientHttpRequestFactory implements ClientHttpRequestFactory, DisposableBean { private OkHttpClient client; @@ -106,11 +104,6 @@ public class OkHttp3ClientHttpRequestFactory return new OkHttp3ClientHttpRequest(this.client, uri, httpMethod); } - @Override - public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) { - return new OkHttp3AsyncClientHttpRequest(this.client, uri, httpMethod); - } - @Override public void destroy() throws IOException { diff --git a/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingAsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingAsyncClientHttpRequest.java deleted file mode 100644 index ec2672534d..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/SimpleBufferingAsyncClientHttpRequest.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2002-2021 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.http.client; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URISyntaxException; - -import org.springframework.core.task.AsyncListenableTaskExecutor; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.util.FileCopyUtils; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * {@link org.springframework.http.client.ClientHttpRequest} implementation that uses - * standard JDK facilities to execute buffered requests. Created via the - * {@link org.springframework.http.client.SimpleClientHttpRequestFactory}. - * - * @author Arjen Poutsma - * @since 3.0 - * @see org.springframework.http.client.SimpleClientHttpRequestFactory#createRequest - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -final class SimpleBufferingAsyncClientHttpRequest extends AbstractBufferingAsyncClientHttpRequest { - - private final HttpURLConnection connection; - - private final boolean outputStreaming; - - private final AsyncListenableTaskExecutor taskExecutor; - - - SimpleBufferingAsyncClientHttpRequest(HttpURLConnection connection, - boolean outputStreaming, AsyncListenableTaskExecutor taskExecutor) { - - this.connection = connection; - this.outputStreaming = outputStreaming; - this.taskExecutor = taskExecutor; - } - - - @Override - public String getMethodValue() { - return this.connection.getRequestMethod(); - } - - @Override - public URI getURI() { - try { - return this.connection.getURL().toURI(); - } - catch (URISyntaxException ex) { - throw new IllegalStateException("Could not get HttpURLConnection URI: " + ex.getMessage(), ex); - } - } - - @Override - protected ListenableFuture executeInternal( - HttpHeaders headers, byte[] bufferedOutput) throws IOException { - - return this.taskExecutor.submitListenable(() -> { - SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers); - // JDK <1.8 doesn't support getOutputStream with HTTP DELETE - if (getMethod() == HttpMethod.DELETE && bufferedOutput.length == 0) { - this.connection.setDoOutput(false); - } - if (this.connection.getDoOutput() && this.outputStreaming) { - this.connection.setFixedLengthStreamingMode(bufferedOutput.length); - } - this.connection.connect(); - if (this.connection.getDoOutput()) { - FileCopyUtils.copy(bufferedOutput, this.connection.getOutputStream()); - } - else { - // Immediately trigger the request in a no-output scenario as well - this.connection.getResponseCode(); - } - return new SimpleClientHttpResponse(this.connection); - }); - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/SimpleClientHttpRequestFactory.java b/spring-web/src/main/java/org/springframework/http/client/SimpleClientHttpRequestFactory.java index 4674df6e47..091b345a26 100644 --- a/spring-web/src/main/java/org/springframework/http/client/SimpleClientHttpRequestFactory.java +++ b/spring-web/src/main/java/org/springframework/http/client/SimpleClientHttpRequestFactory.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2021 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. @@ -23,10 +23,8 @@ import java.net.URI; import java.net.URL; import java.net.URLConnection; -import org.springframework.core.task.AsyncListenableTaskExecutor; import org.springframework.http.HttpMethod; import org.springframework.lang.Nullable; -import org.springframework.util.Assert; /** * {@link ClientHttpRequestFactory} implementation that uses standard JDK facilities. @@ -37,8 +35,7 @@ import org.springframework.util.Assert; * @see java.net.HttpURLConnection * @see HttpComponentsClientHttpRequestFactory */ -@SuppressWarnings("deprecation") -public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory { +public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory { private static final int DEFAULT_CHUNK_SIZE = 4096; @@ -56,9 +53,6 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory, private boolean outputStreaming = true; - @Nullable - private AsyncListenableTaskExecutor taskExecutor; - /** * Set the {@link Proxy} to use for this request factory. @@ -130,15 +124,6 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory, this.outputStreaming = outputStreaming; } - /** - * Set the task executor for this request factory. Setting this property is required - * for {@linkplain #createAsyncRequest(URI, HttpMethod) creating asynchronous requests}. - * @param taskExecutor the task executor - */ - public void setTaskExecutor(AsyncListenableTaskExecutor taskExecutor) { - this.taskExecutor = taskExecutor; - } - @Override public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException { @@ -153,27 +138,6 @@ public class SimpleClientHttpRequestFactory implements ClientHttpRequestFactory, } } - /** - * {@inheritDoc} - *

Setting the {@link #setTaskExecutor taskExecutor} property is required before calling this method. - */ - @Override - public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) throws IOException { - Assert.state(this.taskExecutor != null, "Asynchronous execution requires TaskExecutor to be set"); - - HttpURLConnection connection = openConnection(uri.toURL(), this.proxy); - prepareConnection(connection, httpMethod.name()); - - if (this.bufferRequestBody) { - return new SimpleBufferingAsyncClientHttpRequest( - connection, this.outputStreaming, this.taskExecutor); - } - else { - return new SimpleStreamingAsyncClientHttpRequest( - connection, this.chunkSize, this.outputStreaming, this.taskExecutor); - } - } - /** * Opens and returns a connection to the given URL. *

The default implementation uses the given {@linkplain #setProxy(java.net.Proxy) proxy} - diff --git a/spring-web/src/main/java/org/springframework/http/client/SimpleStreamingAsyncClientHttpRequest.java b/spring-web/src/main/java/org/springframework/http/client/SimpleStreamingAsyncClientHttpRequest.java deleted file mode 100644 index eb8ef1adf8..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/SimpleStreamingAsyncClientHttpRequest.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2002-2020 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.http.client; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URI; -import java.net.URISyntaxException; - -import org.springframework.core.task.AsyncListenableTaskExecutor; -import org.springframework.http.HttpHeaders; -import org.springframework.lang.Nullable; -import org.springframework.util.StreamUtils; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * {@link org.springframework.http.client.ClientHttpRequest} implementation - * that uses standard Java facilities to execute streaming requests. Created - * via the {@link org.springframework.http.client.SimpleClientHttpRequestFactory}. - * - * @author Arjen Poutsma - * @since 3.0 - * @see org.springframework.http.client.SimpleClientHttpRequestFactory#createRequest - * @see org.springframework.http.client.support.AsyncHttpAccessor - * @see org.springframework.web.client.AsyncRestTemplate - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -final class SimpleStreamingAsyncClientHttpRequest extends AbstractAsyncClientHttpRequest { - - private final HttpURLConnection connection; - - private final int chunkSize; - - @Nullable - private OutputStream body; - - private final boolean outputStreaming; - - private final AsyncListenableTaskExecutor taskExecutor; - - - SimpleStreamingAsyncClientHttpRequest(HttpURLConnection connection, int chunkSize, - boolean outputStreaming, AsyncListenableTaskExecutor taskExecutor) { - - this.connection = connection; - this.chunkSize = chunkSize; - this.outputStreaming = outputStreaming; - this.taskExecutor = taskExecutor; - } - - - @Override - public String getMethodValue() { - return this.connection.getRequestMethod(); - } - - @Override - public URI getURI() { - try { - return this.connection.getURL().toURI(); - } - catch (URISyntaxException ex) { - throw new IllegalStateException( - "Could not get HttpURLConnection URI: " + ex.getMessage(), ex); - } - } - - @Override - protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException { - if (this.body == null) { - if (this.outputStreaming) { - long contentLength = headers.getContentLength(); - if (contentLength >= 0) { - this.connection.setFixedLengthStreamingMode(contentLength); - } - else { - this.connection.setChunkedStreamingMode(this.chunkSize); - } - } - SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers); - this.connection.connect(); - this.body = this.connection.getOutputStream(); - } - return StreamUtils.nonClosing(this.body); - } - - @Override - protected ListenableFuture executeInternal(HttpHeaders headers) throws IOException { - return this.taskExecutor.submitListenable(() -> { - try { - if (this.body != null) { - this.body.close(); - } - else { - SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers); - this.connection.connect(); - // Immediately trigger the request in a no-output scenario as well - this.connection.getResponseCode(); - } - } - catch (IOException ex) { - // ignore - } - return new SimpleClientHttpResponse(this.connection); - }); - - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/support/AsyncHttpAccessor.java b/spring-web/src/main/java/org/springframework/http/client/support/AsyncHttpAccessor.java deleted file mode 100644 index faf8c309c7..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/support/AsyncHttpAccessor.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2018 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.http.client.support; - -import java.io.IOException; -import java.net.URI; - -import org.apache.commons.logging.Log; - -import org.springframework.http.HttpLogging; -import org.springframework.http.HttpMethod; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; - -/** - * Base class for {@link org.springframework.web.client.AsyncRestTemplate} - * and other HTTP accessing gateway helpers, defining common properties - * such as the {@link org.springframework.http.client.AsyncClientHttpRequestFactory} - * to operate on. - * - *

Not intended to be used directly. See - * {@link org.springframework.web.client.AsyncRestTemplate}. - * - * @author Arjen Poutsma - * @since 4.0 - * @see org.springframework.web.client.AsyncRestTemplate - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -public class AsyncHttpAccessor { - - /** Logger available to subclasses. */ - protected final Log logger = HttpLogging.forLogName(getClass()); - - @Nullable - private org.springframework.http.client.AsyncClientHttpRequestFactory asyncRequestFactory; - - - /** - * Set the request factory that this accessor uses for obtaining {@link - * org.springframework.http.client.ClientHttpRequest HttpRequests}. - */ - public void setAsyncRequestFactory( - org.springframework.http.client.AsyncClientHttpRequestFactory asyncRequestFactory) { - - Assert.notNull(asyncRequestFactory, "AsyncClientHttpRequestFactory must not be null"); - this.asyncRequestFactory = asyncRequestFactory; - } - - /** - * Return the request factory that this accessor uses for obtaining {@link - * org.springframework.http.client.ClientHttpRequest HttpRequests}. - */ - public org.springframework.http.client.AsyncClientHttpRequestFactory getAsyncRequestFactory() { - Assert.state(this.asyncRequestFactory != null, "No AsyncClientHttpRequestFactory set"); - return this.asyncRequestFactory; - } - - /** - * Create a new {@link org.springframework.http.client.AsyncClientHttpRequest} via this template's - * {@link org.springframework.http.client.AsyncClientHttpRequestFactory}. - * @param url the URL to connect to - * @param method the HTTP method to execute (GET, POST, etc.) - * @return the created request - * @throws IOException in case of I/O errors - */ - protected org.springframework.http.client.AsyncClientHttpRequest createAsyncRequest(URI url, HttpMethod method) - throws IOException { - - org.springframework.http.client.AsyncClientHttpRequest request = - getAsyncRequestFactory().createAsyncRequest(url, method); - if (logger.isDebugEnabled()) { - logger.debug("Created asynchronous " + method.name() + " request for \"" + url + "\""); - } - return request; - } - -} diff --git a/spring-web/src/main/java/org/springframework/http/client/support/InterceptingAsyncHttpAccessor.java b/spring-web/src/main/java/org/springframework/http/client/support/InterceptingAsyncHttpAccessor.java deleted file mode 100644 index 9f8586ec84..0000000000 --- a/spring-web/src/main/java/org/springframework/http/client/support/InterceptingAsyncHttpAccessor.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2002-2017 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.http.client.support; - -import java.util.ArrayList; -import java.util.List; - -import org.springframework.util.CollectionUtils; - -/** - * The HTTP accessor that extends the base {@link AsyncHttpAccessor} with - * request intercepting functionality. - * - * @author Jakub Narloch - * @author Rossen Stoyanchev - * @since 4.3 - * @deprecated as of Spring 5.0, with no direct replacement - */ -@Deprecated -public abstract class InterceptingAsyncHttpAccessor extends AsyncHttpAccessor { - - private List interceptors = - new ArrayList<>(); - - - /** - * Set the request interceptors that this accessor should use. - * @param interceptors the list of interceptors - */ - public void setInterceptors(List interceptors) { - this.interceptors = interceptors; - } - - /** - * Return the request interceptor that this accessor uses. - */ - public List getInterceptors() { - return this.interceptors; - } - - - @Override - public org.springframework.http.client.AsyncClientHttpRequestFactory getAsyncRequestFactory() { - org.springframework.http.client.AsyncClientHttpRequestFactory delegate = super.getAsyncRequestFactory(); - if (!CollectionUtils.isEmpty(getInterceptors())) { - return new org.springframework.http.client.InterceptingAsyncClientHttpRequestFactory(delegate, getInterceptors()); - } - else { - return delegate; - } - } - -} diff --git a/spring-web/src/main/java/org/springframework/web/client/AsyncRequestCallback.java b/spring-web/src/main/java/org/springframework/web/client/AsyncRequestCallback.java deleted file mode 100644 index 00e2fdd4ab..0000000000 --- a/spring-web/src/main/java/org/springframework/web/client/AsyncRequestCallback.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2002-2021 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.web.client; - -import java.io.IOException; - -/** - * Callback interface for code that operates on an - * {@link org.springframework.http.client.AsyncClientHttpRequest}. Allows to - * manipulate the request headers, and write to the request body. - * - *

Used internally by the {@link AsyncRestTemplate}, but also useful for - * application code. - * - * @author Arjen Poutsma - * @since 4.0 - * @see org.springframework.web.client.AsyncRestTemplate#execute - * @deprecated as of Spring 5.0, in favor of - * {@link org.springframework.web.reactive.function.client.ExchangeFilterFunction} - */ -@FunctionalInterface -@Deprecated -public interface AsyncRequestCallback { - - /** - * Gets called by {@link AsyncRestTemplate#execute} with an opened {@code ClientHttpRequest}. - * Does not need to care about closing the request or about handling errors: - * this will all be handled by the {@code RestTemplate}. - * @param request the active HTTP request - * @throws java.io.IOException in case of I/O errors - */ - void doWithRequest(org.springframework.http.client.AsyncClientHttpRequest request) throws IOException; - -} diff --git a/spring-web/src/main/java/org/springframework/web/client/AsyncRestOperations.java b/spring-web/src/main/java/org/springframework/web/client/AsyncRestOperations.java deleted file mode 100644 index c9d92a2aff..0000000000 --- a/spring-web/src/main/java/org/springframework/web/client/AsyncRestOperations.java +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright 2002-2017 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.web.client; - -import java.net.URI; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.Future; - -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.lang.Nullable; -import org.springframework.util.concurrent.ListenableFuture; - -/** - * Interface specifying a basic set of asynchronous RESTful operations. - * Implemented by {@link AsyncRestTemplate}. Not often used directly, but a useful - * option to enhance testability, as it can easily be mocked or stubbed. - * - * @author Arjen Poutsma - * @since 4.0 - * @see AsyncRestTemplate - * @see RestOperations - * @deprecated as of Spring 5.0, in favor of {@link org.springframework.web.reactive.function.client.WebClient} - */ -@Deprecated -public interface AsyncRestOperations { - - /** - * Expose the synchronous Spring RestTemplate to allow synchronous invocation. - */ - RestOperations getRestOperations(); - - - // GET - - /** - * Asynchronously retrieve an entity by doing a GET on the specified URL. - * The response is converted and stored in an {@link ResponseEntity}. - *

URI Template variables are expanded using the given URI variables, if any. - * @param url the URL - * @param responseType the type of the return value - * @param uriVariables the variables to expand the template - * @return the entity wrapped in a {@link Future} - */ - ListenableFuture> getForEntity(String url, Class responseType, - Object... uriVariables) throws RestClientException; - - /** - * Asynchronously retrieve a representation by doing a GET on the URI template. - * The response is converted and stored in an {@link ResponseEntity}. - *

URI Template variables are expanded using the given map. - * @param url the URL - * @param responseType the type of the return value - * @param uriVariables the map containing variables for the URI template - * @return the entity wrapped in a {@link Future} - */ - ListenableFuture> getForEntity(String url, Class responseType, - Map uriVariables) throws RestClientException; - - /** - * Asynchronously retrieve a representation by doing a GET on the URL. - * The response is converted and stored in an {@link ResponseEntity}. - * @param url the URL - * @param responseType the type of the return value - * @return the entity wrapped in a {@link Future} - */ - ListenableFuture> getForEntity(URI url, Class responseType) - throws RestClientException; - - - // HEAD - - /** - * Asynchronously retrieve all headers of the resource specified by the URI template. - *

URI Template variables are expanded using the given URI variables, if any. - * @param url the URL - * @param uriVariables the variables to expand the template - * @return all HTTP headers of that resource wrapped in a {@link Future} - */ - ListenableFuture headForHeaders(String url, Object... uriVariables) - throws RestClientException; - - /** - * Asynchronously retrieve all headers of the resource specified by the URI template. - *

URI Template variables are expanded using the given map. - * @param url the URL - * @param uriVariables the map containing variables for the URI template - * @return all HTTP headers of that resource wrapped in a {@link Future} - */ - ListenableFuture headForHeaders(String url, Map uriVariables) - throws RestClientException; - - /** - * Asynchronously retrieve all headers of the resource specified by the URL. - * @param url the URL - * @return all HTTP headers of that resource wrapped in a {@link Future} - */ - ListenableFuture headForHeaders(URI url) throws RestClientException; - - - // POST - - /** - * Create a new resource by POSTing the given object to the URI template, and - * asynchronously returns the value of the {@code Location} header. This header - * typically indicates where the new resource is stored. - *

URI Template variables are expanded using the given URI variables, if any. - * @param url the URL - * @param request the Object to be POSTed (may be {@code null}) - * @param uriVariables the variables to expand the template - * @return the value for the {@code Location} header wrapped in a {@link Future} - * @see org.springframework.http.HttpEntity - */ - ListenableFuture postForLocation(String url, @Nullable HttpEntity request, Object... uriVariables) - throws RestClientException; - - /** - * Create a new resource by POSTing the given object to the URI template, and - * asynchronously returns the value of the {@code Location} header. This header - * typically indicates where the new resource is stored. - *

URI Template variables are expanded using the given map. - * @param url the URL - * @param request the Object to be POSTed (may be {@code null}) - * @param uriVariables the variables to expand the template - * @return the value for the {@code Location} header wrapped in a {@link Future} - * @see org.springframework.http.HttpEntity - */ - ListenableFuture postForLocation(String url, @Nullable HttpEntity request, Map uriVariables) - throws RestClientException; - - /** - * Create a new resource by POSTing the given object to the URL, and asynchronously - * returns the value of the {@code Location} header. This header typically indicates - * where the new resource is stored. - * @param url the URL - * @param request the Object to be POSTed (may be {@code null}) - * @return the value for the {@code Location} header wrapped in a {@link Future} - * @see org.springframework.http.HttpEntity - */ - ListenableFuture postForLocation(URI url, @Nullable HttpEntity request) throws RestClientException; - - /** - * Create a new resource by POSTing the given object to the URI template, - * and asynchronously returns the response as {@link ResponseEntity}. - *

URI Template variables are expanded using the given URI variables, if any. - * @param url the URL - * @param request the Object to be POSTed (may be {@code null}) - * @param uriVariables the variables to expand the template - * @return the entity wrapped in a {@link Future} - * @see org.springframework.http.HttpEntity - */ - ListenableFuture> postForEntity(String url, @Nullable HttpEntity request, - Class responseType, Object... uriVariables) throws RestClientException; - - /** - * Create a new resource by POSTing the given object to the URI template, - * and asynchronously returns the response as {@link ResponseEntity}. - *

URI Template variables are expanded using the given map. - * @param url the URL - * @param request the Object to be POSTed (may be {@code null}) - * @param uriVariables the variables to expand the template - * @return the entity wrapped in a {@link Future} - * @see org.springframework.http.HttpEntity - */ - ListenableFuture> postForEntity(String url, @Nullable HttpEntity request, - Class responseType, Map uriVariables) throws RestClientException; - - /** - * Create a new resource by POSTing the given object to the URL, - * and asynchronously returns the response as {@link ResponseEntity}. - * @param url the URL - * @param request the Object to be POSTed (may be {@code null}) - * @return the entity wrapped in a {@link Future} - * @see org.springframework.http.HttpEntity - */ - ListenableFuture> postForEntity(URI url, @Nullable HttpEntity request, - Class responseType) throws RestClientException; - - - // PUT - - /** - * Create or update a resource by PUTting the given object to the URI. - *

URI Template variables are expanded using the given URI variables, if any. - *

The Future will return a {@code null} result upon completion. - * @param url the URL - * @param request the Object to be PUT (may be {@code null}) - * @param uriVariables the variables to expand the template - * @see HttpEntity - */ - ListenableFuture put(String url, @Nullable HttpEntity request, Object... uriVariables) - throws RestClientException; - - /** - * Creates a new resource by PUTting the given object to URI template. - *

URI Template variables are expanded using the given map. - *

The Future will return a {@code null} result upon completion. - * @param url the URL - * @param request the Object to be PUT (may be {@code null}) - * @param uriVariables the variables to expand the template - * @see HttpEntity - */ - ListenableFuture put(String url, @Nullable HttpEntity request, Map uriVariables) - throws RestClientException; - - /** - * Creates a new resource by PUTting the given object to URL. - *

The Future will return a {@code null} result upon completion. - * @param url the URL - * @param request the Object to be PUT (may be {@code null}) - * @see HttpEntity - */ - ListenableFuture put(URI url, @Nullable HttpEntity request) throws RestClientException; - - - // DELETE - - /** - * Asynchronously delete the resources at the specified URI. - *

URI Template variables are expanded using the given URI variables, if any. - *

The Future will return a {@code null} result upon completion. - * @param url the URL - * @param uriVariables the variables to expand in the template - */ - ListenableFuture delete(String url, Object... uriVariables) throws RestClientException; - - /** - * Asynchronously delete the resources at the specified URI. - *

URI Template variables are expanded using the given URI variables, if any. - *

The Future will return a {@code null} result upon completion. - * @param url the URL - * @param uriVariables the variables to expand in the template - */ - ListenableFuture delete(String url, Map uriVariables) throws RestClientException; - - /** - * Asynchronously delete the resources at the specified URI. - *

URI Template variables are expanded using the given URI variables, if any. - *

The Future will return a {@code null} result upon completion. - * @param url the URL - */ - ListenableFuture delete(URI url) throws RestClientException; - - - // OPTIONS - - /** - * Asynchronously return the value of the Allow header for the given URI. - *

URI Template variables are expanded using the given URI variables, if any. - * @param url the URL - * @param uriVariables the variables to expand in the template - * @return the value of the allow header wrapped in a {@link Future} - */ - ListenableFuture> optionsForAllow(String url, Object... uriVariables) - throws RestClientException; - - /** - * Asynchronously return the value of the Allow header for the given URI. - *

URI Template variables are expanded using the given map. - * @param url the URL - * @param uriVariables the variables to expand in the template - * @return the value of the allow header wrapped in a {@link Future} - */ - ListenableFuture> optionsForAllow(String url, Map uriVariables) - throws RestClientException; - - /** - * Asynchronously return the value of the Allow header for the given URL. - * @param url the URL - * @return the value of the allow header wrapped in a {@link Future} - */ - ListenableFuture> optionsForAllow(URI url) throws RestClientException; - - - // exchange - - /** - * Asynchronously execute the HTTP method to the given URI template, writing the - * given request entity to the request, and returns the response as - * {@link ResponseEntity}. - *

URI Template variables are expanded using the given URI variables, if any. - * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestEntity the entity (headers and/or body) to write to the request - * (may be {@code null}) - * @param responseType the type of the return value - * @param uriVariables the variables to expand in the template - * @return the response as entity wrapped in a {@link Future} - */ - ListenableFuture> exchange(String url, HttpMethod method, - @Nullable HttpEntity requestEntity, Class responseType, Object... uriVariables) - throws RestClientException; - - /** - * Asynchronously execute the HTTP method to the given URI template, writing the - * given request entity to the request, and returns the response as - * {@link ResponseEntity}. - *

URI Template variables are expanded using the given URI variables, if any. - * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestEntity the entity (headers and/or body) to write to the request - * (may be {@code null}) - * @param responseType the type of the return value - * @param uriVariables the variables to expand in the template - * @return the response as entity wrapped in a {@link Future} - */ - ListenableFuture> exchange(String url, HttpMethod method, - @Nullable HttpEntity requestEntity, Class responseType, - Map uriVariables) throws RestClientException; - - /** - * Asynchronously execute the HTTP method to the given URI template, writing the - * given request entity to the request, and returns the response as - * {@link ResponseEntity}. - * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestEntity the entity (headers and/or body) to write to the request - * (may be {@code null}) - * @param responseType the type of the return value - * @return the response as entity wrapped in a {@link Future} - */ - ListenableFuture> exchange(URI url, HttpMethod method, - @Nullable HttpEntity requestEntity, Class responseType) - throws RestClientException; - - /** - * Asynchronously execute the HTTP method to the given URI template, writing the given - * request entity to the request, and returns the response as {@link ResponseEntity}. - * The given {@link ParameterizedTypeReference} is used to pass generic type - * information: - *

-	 * ParameterizedTypeReference<List<MyBean>> myBean =
-	 *     new ParameterizedTypeReference<List<MyBean>>() {};
-	 *
-	 * ResponseEntity<List<MyBean>> response =
-	 *     template.exchange("https://example.com",HttpMethod.GET, null, myBean);
-	 * 
- * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestEntity the entity (headers and/or body) to write to the - * request (may be {@code null}) - * @param responseType the type of the return value - * @param uriVariables the variables to expand in the template - * @return the response as entity wrapped in a {@link Future} - */ - ListenableFuture> exchange(String url, HttpMethod method, - @Nullable HttpEntity requestEntity, ParameterizedTypeReference responseType, - Object... uriVariables) throws RestClientException; - - /** - * Asynchronously execute the HTTP method to the given URI template, writing the given - * request entity to the request, and returns the response as {@link ResponseEntity}. - * The given {@link ParameterizedTypeReference} is used to pass generic type - * information: - *
-	 * ParameterizedTypeReference<List<MyBean>> myBean =
-	 *     new ParameterizedTypeReference<List<MyBean>>() {};
-	 *
-	 * ResponseEntity<List<MyBean>> response =
-	 *     template.exchange("https://example.com",HttpMethod.GET, null, myBean);
-	 * 
- * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestEntity the entity (headers and/or body) to write to the request - * (may be {@code null}) - * @param responseType the type of the return value - * @param uriVariables the variables to expand in the template - * @return the response as entity wrapped in a {@link Future} - */ - ListenableFuture> exchange(String url, HttpMethod method, - @Nullable HttpEntity requestEntity, ParameterizedTypeReference responseType, - Map uriVariables) throws RestClientException; - - /** - * Asynchronously execute the HTTP method to the given URI template, writing the given - * request entity to the request, and returns the response as {@link ResponseEntity}. - * The given {@link ParameterizedTypeReference} is used to pass generic type - * information: - *
-	 * ParameterizedTypeReference<List<MyBean>> myBean =
-	 *     new ParameterizedTypeReference<List<MyBean>>() {};
-	 *
-	 * ResponseEntity<List<MyBean>> response =
-	 *     template.exchange("https://example.com",HttpMethod.GET, null, myBean);
-	 * 
- * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestEntity the entity (headers and/or body) to write to the request - * (may be {@code null}) - * @param responseType the type of the return value - * @return the response as entity wrapped in a {@link Future} - */ - ListenableFuture> exchange(URI url, HttpMethod method, - @Nullable HttpEntity requestEntity, ParameterizedTypeReference responseType) - throws RestClientException; - - - // general execution - - /** - * Asynchronously execute the HTTP method to the given URI template, preparing the - * request with the {@link AsyncRequestCallback}, and reading the response with a - * {@link ResponseExtractor}. - *

URI Template variables are expanded using the given URI variables, if any. - * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestCallback object that prepares the request - * @param responseExtractor object that extracts the return value from the response - * @param uriVariables the variables to expand in the template - * @return an arbitrary object, as returned by the {@link ResponseExtractor} - */ - ListenableFuture execute(String url, HttpMethod method, - @Nullable AsyncRequestCallback requestCallback, @Nullable ResponseExtractor responseExtractor, - Object... uriVariables) throws RestClientException; - - /** - * Asynchronously execute the HTTP method to the given URI template, preparing the - * request with the {@link AsyncRequestCallback}, and reading the response with a - * {@link ResponseExtractor}. - *

URI Template variables are expanded using the given URI variables map. - * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestCallback object that prepares the request - * @param responseExtractor object that extracts the return value from the response - * @param uriVariables the variables to expand in the template - * @return an arbitrary object, as returned by the {@link ResponseExtractor} - */ - ListenableFuture execute(String url, HttpMethod method, - @Nullable AsyncRequestCallback requestCallback, @Nullable ResponseExtractor responseExtractor, - Map uriVariables) throws RestClientException; - - /** - * Asynchronously execute the HTTP method to the given URL, preparing the request - * with the {@link AsyncRequestCallback}, and reading the response with a - * {@link ResponseExtractor}. - * @param url the URL - * @param method the HTTP method (GET, POST, etc) - * @param requestCallback object that prepares the request - * @param responseExtractor object that extracts the return value from the response - * @return an arbitrary object, as returned by the {@link ResponseExtractor} - */ - ListenableFuture execute(URI url, HttpMethod method, - @Nullable AsyncRequestCallback requestCallback, @Nullable ResponseExtractor responseExtractor) - throws RestClientException; - -} diff --git a/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java b/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java deleted file mode 100644 index f94359de4a..0000000000 --- a/spring-web/src/main/java/org/springframework/web/client/AsyncRestTemplate.java +++ /dev/null @@ -1,714 +0,0 @@ -/* - * Copyright 2002-2018 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.web.client; - -import java.io.IOException; -import java.io.OutputStream; -import java.lang.reflect.Type; -import java.net.URI; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ExecutionException; - -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.core.task.AsyncListenableTaskExecutor; -import org.springframework.core.task.AsyncTaskExecutor; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; -import org.springframework.http.client.ClientHttpRequest; -import org.springframework.http.client.ClientHttpRequestFactory; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.http.client.SimpleClientHttpRequestFactory; -import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.lang.Nullable; -import org.springframework.util.Assert; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.ListenableFutureAdapter; -import org.springframework.web.util.DefaultUriBuilderFactory; -import org.springframework.web.util.UriTemplateHandler; - -/** - * Spring's central class for asynchronous client-side HTTP access. - * Exposes similar methods as {@link RestTemplate}, but returns {@link ListenableFuture} - * wrappers as opposed to concrete results. - * - *

The {@code AsyncRestTemplate} exposes a synchronous {@link RestTemplate} via the - * {@link #getRestOperations()} method and shares its {@linkplain #setErrorHandler error handler} - * and {@linkplain #setMessageConverters message converters} with that {@code RestTemplate}. - * - *

Note: by default {@code AsyncRestTemplate} relies on - * standard JDK facilities to establish HTTP connections. You can switch to use - * a different HTTP library such as Apache HttpComponents, Netty, and OkHttp by - * using a constructor accepting an {@link org.springframework.http.client.AsyncClientHttpRequestFactory}. - * - *

For more information, please refer to the {@link RestTemplate} API documentation. - * - * @author Arjen Poutsma - * @since 4.0 - * @see RestTemplate - * @deprecated as of Spring 5.0, in favor of {@link org.springframework.web.reactive.function.client.WebClient} - */ -@Deprecated -public class AsyncRestTemplate extends org.springframework.http.client.support.InterceptingAsyncHttpAccessor - implements AsyncRestOperations { - - private final RestTemplate syncTemplate; - - - /** - * Create a new instance of the {@code AsyncRestTemplate} using default settings. - *

This constructor uses a {@link SimpleClientHttpRequestFactory} in combination - * with a {@link SimpleAsyncTaskExecutor} for asynchronous execution. - */ - public AsyncRestTemplate() { - this(new SimpleAsyncTaskExecutor()); - } - - /** - * Create a new instance of the {@code AsyncRestTemplate} using the given - * {@link AsyncTaskExecutor}. - *

This constructor uses a {@link SimpleClientHttpRequestFactory} in combination - * with the given {@code AsyncTaskExecutor} for asynchronous execution. - */ - public AsyncRestTemplate(AsyncListenableTaskExecutor taskExecutor) { - Assert.notNull(taskExecutor, "AsyncTaskExecutor must not be null"); - SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); - requestFactory.setTaskExecutor(taskExecutor); - this.syncTemplate = new RestTemplate(requestFactory); - setAsyncRequestFactory(requestFactory); - } - - /** - * Create a new instance of the {@code AsyncRestTemplate} using the given - * {@link org.springframework.http.client.AsyncClientHttpRequestFactory}. - *

This constructor will cast the given asynchronous - * {@code AsyncClientHttpRequestFactory} to a {@link ClientHttpRequestFactory}. Since - * all implementations of {@code ClientHttpRequestFactory} provided in Spring also - * implement {@code AsyncClientHttpRequestFactory}, this should not result in a - * {@code ClassCastException}. - */ - public AsyncRestTemplate(org.springframework.http.client.AsyncClientHttpRequestFactory asyncRequestFactory) { - this(asyncRequestFactory, (ClientHttpRequestFactory) asyncRequestFactory); - } - - /** - * Creates a new instance of the {@code AsyncRestTemplate} using the given - * asynchronous and synchronous request factories. - * @param asyncRequestFactory the asynchronous request factory - * @param syncRequestFactory the synchronous request factory - */ - public AsyncRestTemplate(org.springframework.http.client.AsyncClientHttpRequestFactory asyncRequestFactory, - ClientHttpRequestFactory syncRequestFactory) { - - this(asyncRequestFactory, new RestTemplate(syncRequestFactory)); - } - - /** - * Create a new instance of the {@code AsyncRestTemplate} using the given - * {@link org.springframework.http.client.AsyncClientHttpRequestFactory} and synchronous {@link RestTemplate}. - * @param requestFactory the asynchronous request factory to use - * @param restTemplate the synchronous template to use - */ - public AsyncRestTemplate(org.springframework.http.client.AsyncClientHttpRequestFactory requestFactory, - RestTemplate restTemplate) { - - Assert.notNull(restTemplate, "RestTemplate must not be null"); - this.syncTemplate = restTemplate; - setAsyncRequestFactory(requestFactory); - } - - - /** - * Set the error handler. - *

By default, AsyncRestTemplate uses a - * {@link org.springframework.web.client.DefaultResponseErrorHandler}. - */ - public void setErrorHandler(ResponseErrorHandler errorHandler) { - this.syncTemplate.setErrorHandler(errorHandler); - } - - /** - * Return the error handler. - */ - public ResponseErrorHandler getErrorHandler() { - return this.syncTemplate.getErrorHandler(); - } - - /** - * Configure default URI variable values. This is a shortcut for: - *

-	 * DefaultUriTemplateHandler handler = new DefaultUriTemplateHandler();
-	 * handler.setDefaultUriVariables(...);
-	 *
-	 * AsyncRestTemplate restTemplate = new AsyncRestTemplate();
-	 * restTemplate.setUriTemplateHandler(handler);
-	 * 
- * @param defaultUriVariables the default URI variable values - * @since 4.3 - */ - @SuppressWarnings("deprecation") - public void setDefaultUriVariables(Map defaultUriVariables) { - UriTemplateHandler handler = this.syncTemplate.getUriTemplateHandler(); - if (handler instanceof DefaultUriBuilderFactory) { - ((DefaultUriBuilderFactory) handler).setDefaultUriVariables(defaultUriVariables); - } - else if (handler instanceof org.springframework.web.util.AbstractUriTemplateHandler) { - ((org.springframework.web.util.AbstractUriTemplateHandler) handler) - .setDefaultUriVariables(defaultUriVariables); - } - else { - throw new IllegalArgumentException( - "This property is not supported with the configured UriTemplateHandler."); - } - } - - /** - * This property has the same purpose as the corresponding property on the - * {@code RestTemplate}. For more details see - * {@link RestTemplate#setUriTemplateHandler}. - * @param handler the URI template handler to use - */ - public void setUriTemplateHandler(UriTemplateHandler handler) { - this.syncTemplate.setUriTemplateHandler(handler); - } - - /** - * Return the configured URI template handler. - */ - public UriTemplateHandler getUriTemplateHandler() { - return this.syncTemplate.getUriTemplateHandler(); - } - - @Override - public RestOperations getRestOperations() { - return this.syncTemplate; - } - - /** - * Set the message body converters to use. - *

These converters are used to convert from and to HTTP requests and responses. - */ - public void setMessageConverters(List> messageConverters) { - this.syncTemplate.setMessageConverters(messageConverters); - } - - /** - * Return the message body converters. - */ - public List> getMessageConverters() { - return this.syncTemplate.getMessageConverters(); - } - - - // GET - - @Override - public ListenableFuture> getForEntity(String url, Class responseType, Object... uriVariables) - throws RestClientException { - - AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); - } - - @Override - public ListenableFuture> getForEntity(String url, Class responseType, - Map uriVariables) throws RestClientException { - - AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables); - } - - @Override - public ListenableFuture> getForEntity(URI url, Class responseType) - throws RestClientException { - - AsyncRequestCallback requestCallback = acceptHeaderRequestCallback(responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, HttpMethod.GET, requestCallback, responseExtractor); - } - - - // HEAD - - @Override - public ListenableFuture headForHeaders(String url, Object... uriVariables) - throws RestClientException { - - ResponseExtractor headersExtractor = headersExtractor(); - return execute(url, HttpMethod.HEAD, null, headersExtractor, uriVariables); - } - - @Override - public ListenableFuture headForHeaders(String url, Map uriVariables) - throws RestClientException { - - ResponseExtractor headersExtractor = headersExtractor(); - return execute(url, HttpMethod.HEAD, null, headersExtractor, uriVariables); - } - - @Override - public ListenableFuture headForHeaders(URI url) throws RestClientException { - ResponseExtractor headersExtractor = headersExtractor(); - return execute(url, HttpMethod.HEAD, null, headersExtractor); - } - - - // POST - - @Override - public ListenableFuture postForLocation(String url, @Nullable HttpEntity request, Object... uriVars) - throws RestClientException { - - AsyncRequestCallback callback = httpEntityCallback(request); - ResponseExtractor extractor = headersExtractor(); - ListenableFuture future = execute(url, HttpMethod.POST, callback, extractor, uriVars); - return adaptToLocationHeader(future); - } - - @Override - public ListenableFuture postForLocation(String url, @Nullable HttpEntity request, Map uriVars) - throws RestClientException { - - AsyncRequestCallback callback = httpEntityCallback(request); - ResponseExtractor extractor = headersExtractor(); - ListenableFuture future = execute(url, HttpMethod.POST, callback, extractor, uriVars); - return adaptToLocationHeader(future); - } - - @Override - public ListenableFuture postForLocation(URI url, @Nullable HttpEntity request) - throws RestClientException { - - AsyncRequestCallback callback = httpEntityCallback(request); - ResponseExtractor extractor = headersExtractor(); - ListenableFuture future = execute(url, HttpMethod.POST, callback, extractor); - return adaptToLocationHeader(future); - } - - private static ListenableFuture adaptToLocationHeader(ListenableFuture future) { - return new ListenableFutureAdapter(future) { - @Override - @Nullable - protected URI adapt(HttpHeaders headers) throws ExecutionException { - return headers.getLocation(); - } - }; - } - - @Override - public ListenableFuture> postForEntity(String url, @Nullable HttpEntity request, - Class responseType, Object... uriVariables) throws RestClientException { - - AsyncRequestCallback requestCallback = httpEntityCallback(request, responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables); - } - - @Override - public ListenableFuture> postForEntity(String url, @Nullable HttpEntity request, - Class responseType, Map uriVariables) throws RestClientException { - - AsyncRequestCallback requestCallback = httpEntityCallback(request, responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, HttpMethod.POST, requestCallback, responseExtractor, uriVariables); - } - - @Override - public ListenableFuture> postForEntity(URI url, - @Nullable HttpEntity request, Class responseType) throws RestClientException { - - AsyncRequestCallback requestCallback = httpEntityCallback(request, responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, HttpMethod.POST, requestCallback, responseExtractor); - } - - - // PUT - - @Override - public ListenableFuture put(String url, @Nullable HttpEntity request, Object... uriVars) - throws RestClientException { - - AsyncRequestCallback requestCallback = httpEntityCallback(request); - return execute(url, HttpMethod.PUT, requestCallback, null, uriVars); - } - - @Override - public ListenableFuture put(String url, @Nullable HttpEntity request, Map uriVars) - throws RestClientException { - - AsyncRequestCallback requestCallback = httpEntityCallback(request); - return execute(url, HttpMethod.PUT, requestCallback, null, uriVars); - } - - @Override - public ListenableFuture put(URI url, @Nullable HttpEntity request) throws RestClientException { - AsyncRequestCallback requestCallback = httpEntityCallback(request); - return execute(url, HttpMethod.PUT, requestCallback, null); - } - - - // DELETE - - @Override - public ListenableFuture delete(String url, Object... uriVariables) throws RestClientException { - return execute(url, HttpMethod.DELETE, null, null, uriVariables); - } - - @Override - public ListenableFuture delete(String url, Map uriVariables) throws RestClientException { - return execute(url, HttpMethod.DELETE, null, null, uriVariables); - } - - @Override - public ListenableFuture delete(URI url) throws RestClientException { - return execute(url, HttpMethod.DELETE, null, null); - } - - - // OPTIONS - - @Override - public ListenableFuture> optionsForAllow(String url, Object... uriVars) - throws RestClientException { - - ResponseExtractor extractor = headersExtractor(); - ListenableFuture future = execute(url, HttpMethod.OPTIONS, null, extractor, uriVars); - return adaptToAllowHeader(future); - } - - @Override - public ListenableFuture> optionsForAllow(String url, Map uriVars) - throws RestClientException { - - ResponseExtractor extractor = headersExtractor(); - ListenableFuture future = execute(url, HttpMethod.OPTIONS, null, extractor, uriVars); - return adaptToAllowHeader(future); - } - - @Override - public ListenableFuture> optionsForAllow(URI url) throws RestClientException { - ResponseExtractor extractor = headersExtractor(); - ListenableFuture future = execute(url, HttpMethod.OPTIONS, null, extractor); - return adaptToAllowHeader(future); - } - - private static ListenableFuture> adaptToAllowHeader(ListenableFuture future) { - return new ListenableFutureAdapter, HttpHeaders>(future) { - @Override - protected Set adapt(HttpHeaders headers) throws ExecutionException { - return headers.getAllow(); - } - }; - } - - // exchange - - @Override - public ListenableFuture> exchange(String url, HttpMethod method, - @Nullable HttpEntity requestEntity, Class responseType, Object... uriVariables) - throws RestClientException { - - AsyncRequestCallback requestCallback = httpEntityCallback(requestEntity, responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, method, requestCallback, responseExtractor, uriVariables); - } - - @Override - public ListenableFuture> exchange(String url, HttpMethod method, - @Nullable HttpEntity requestEntity, Class responseType, Map uriVariables) - throws RestClientException { - - AsyncRequestCallback requestCallback = httpEntityCallback(requestEntity, responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, method, requestCallback, responseExtractor, uriVariables); - } - - @Override - public ListenableFuture> exchange(URI url, HttpMethod method, - @Nullable HttpEntity requestEntity, Class responseType) throws RestClientException { - - AsyncRequestCallback requestCallback = httpEntityCallback(requestEntity, responseType); - ResponseExtractor> responseExtractor = responseEntityExtractor(responseType); - return execute(url, method, requestCallback, responseExtractor); - } - - @Override - public ListenableFuture> exchange(String url, HttpMethod method, - @Nullable HttpEntity requestEntity, ParameterizedTypeReference responseType, - Object... uriVariables) throws RestClientException { - - Type type = responseType.getType(); - AsyncRequestCallback requestCallback = httpEntityCallback(requestEntity, type); - ResponseExtractor> responseExtractor = responseEntityExtractor(type); - return execute(url, method, requestCallback, responseExtractor, uriVariables); - } - - @Override - public ListenableFuture> exchange(String url, HttpMethod method, - @Nullable HttpEntity requestEntity, ParameterizedTypeReference responseType, - Map uriVariables) throws RestClientException { - - Type type = responseType.getType(); - AsyncRequestCallback requestCallback = httpEntityCallback(requestEntity, type); - ResponseExtractor> responseExtractor = responseEntityExtractor(type); - return execute(url, method, requestCallback, responseExtractor, uriVariables); - } - - @Override - public ListenableFuture> exchange(URI url, HttpMethod method, - @Nullable HttpEntity requestEntity, ParameterizedTypeReference responseType) - throws RestClientException { - - Type type = responseType.getType(); - AsyncRequestCallback requestCallback = httpEntityCallback(requestEntity, type); - ResponseExtractor> responseExtractor = responseEntityExtractor(type); - return execute(url, method, requestCallback, responseExtractor); - } - - - // general execution - - @Override - public ListenableFuture execute(String url, HttpMethod method, @Nullable AsyncRequestCallback requestCallback, - @Nullable ResponseExtractor responseExtractor, Object... uriVariables) throws RestClientException { - - URI expanded = getUriTemplateHandler().expand(url, uriVariables); - return doExecute(expanded, method, requestCallback, responseExtractor); - } - - @Override - public ListenableFuture execute(String url, HttpMethod method, - @Nullable AsyncRequestCallback requestCallback, @Nullable ResponseExtractor responseExtractor, - Map uriVariables) throws RestClientException { - - URI expanded = getUriTemplateHandler().expand(url, uriVariables); - return doExecute(expanded, method, requestCallback, responseExtractor); - } - - @Override - public ListenableFuture execute(URI url, HttpMethod method, - @Nullable AsyncRequestCallback requestCallback, - @Nullable ResponseExtractor responseExtractor) throws RestClientException { - - return doExecute(url, method, requestCallback, responseExtractor); - } - - /** - * Execute the given method on the provided URI. The - * {@link org.springframework.http.client.ClientHttpRequest} - * is processed using the {@link RequestCallback}; the response with - * the {@link ResponseExtractor}. - * @param url the fully-expanded URL to connect to - * @param method the HTTP method to execute (GET, POST, etc.) - * @param requestCallback object that prepares the request (can be {@code null}) - * @param responseExtractor object that extracts the return value from the response (can - * be {@code null}) - * @return an arbitrary object, as returned by the {@link ResponseExtractor} - */ - protected ListenableFuture doExecute(URI url, HttpMethod method, - @Nullable AsyncRequestCallback requestCallback, - @Nullable ResponseExtractor responseExtractor) throws RestClientException { - - Assert.notNull(url, "'url' must not be null"); - Assert.notNull(method, "'method' must not be null"); - try { - org.springframework.http.client.AsyncClientHttpRequest request = createAsyncRequest(url, method); - if (requestCallback != null) { - requestCallback.doWithRequest(request); - } - ListenableFuture responseFuture = request.executeAsync(); - return new ResponseExtractorFuture<>(method, url, responseFuture, responseExtractor); - } - catch (IOException ex) { - throw new ResourceAccessException("I/O error on " + method.name() + - " request for \"" + url + "\":" + ex.getMessage(), ex); - } - } - - private void logResponseStatus(HttpMethod method, URI url, ClientHttpResponse response) { - if (logger.isDebugEnabled()) { - try { - logger.debug("Async " + method.name() + " request for \"" + url + "\" resulted in " + - response.getRawStatusCode() + " (" + response.getStatusText() + ")"); - } - catch (IOException ex) { - // ignore - } - } - } - - private void handleResponseError(HttpMethod method, URI url, ClientHttpResponse response) throws IOException { - if (logger.isWarnEnabled()) { - try { - logger.warn("Async " + method.name() + " request for \"" + url + "\" resulted in " + - response.getRawStatusCode() + " (" + response.getStatusText() + "); invoking error handler"); - } - catch (IOException ex) { - // ignore - } - } - getErrorHandler().handleError(url, method, response); - } - - /** - * Returns a request callback implementation that prepares the request {@code Accept} - * headers based on the given response type and configured {@linkplain - * #getMessageConverters() message converters}. - */ - protected AsyncRequestCallback acceptHeaderRequestCallback(Class responseType) { - return new AsyncRequestCallbackAdapter(this.syncTemplate.acceptHeaderRequestCallback(responseType)); - } - - /** - * Returns a request callback implementation that writes the given object to the - * request stream. - */ - protected AsyncRequestCallback httpEntityCallback(@Nullable HttpEntity requestBody) { - return new AsyncRequestCallbackAdapter(this.syncTemplate.httpEntityCallback(requestBody)); - } - - /** - * Returns a request callback implementation that writes the given object to the - * request stream. - */ - protected AsyncRequestCallback httpEntityCallback(@Nullable HttpEntity request, Type responseType) { - return new AsyncRequestCallbackAdapter(this.syncTemplate.httpEntityCallback(request, responseType)); - } - - /** - * Returns a response extractor for {@link ResponseEntity}. - */ - protected ResponseExtractor> responseEntityExtractor(Type responseType) { - return this.syncTemplate.responseEntityExtractor(responseType); - } - - /** - * Returns a response extractor for {@link HttpHeaders}. - */ - protected ResponseExtractor headersExtractor() { - return this.syncTemplate.headersExtractor(); - } - - - /** - * Future returned from - * {@link #doExecute(URI, HttpMethod, AsyncRequestCallback, ResponseExtractor)}. - */ - private class ResponseExtractorFuture extends ListenableFutureAdapter { - - private final HttpMethod method; - - private final URI url; - - @Nullable - private final ResponseExtractor responseExtractor; - - public ResponseExtractorFuture(HttpMethod method, URI url, - ListenableFuture clientHttpResponseFuture, - @Nullable ResponseExtractor responseExtractor) { - - super(clientHttpResponseFuture); - this.method = method; - this.url = url; - this.responseExtractor = responseExtractor; - } - - @Override - @Nullable - protected final T adapt(ClientHttpResponse response) throws ExecutionException { - try { - if (!getErrorHandler().hasError(response)) { - logResponseStatus(this.method, this.url, response); - } - else { - handleResponseError(this.method, this.url, response); - } - return convertResponse(response); - } - catch (Throwable ex) { - throw new ExecutionException(ex); - } - finally { - response.close(); - } - } - - @Nullable - protected T convertResponse(ClientHttpResponse response) throws IOException { - return (this.responseExtractor != null ? this.responseExtractor.extractData(response) : null); - } - } - - - /** - * Adapts a {@link RequestCallback} to the {@link AsyncRequestCallback} interface. - */ - private static class AsyncRequestCallbackAdapter implements AsyncRequestCallback { - - private final RequestCallback adaptee; - - /** - * Create a new {@code AsyncRequestCallbackAdapter} from the given - * {@link RequestCallback}. - * @param requestCallback the callback to base this adapter on - */ - public AsyncRequestCallbackAdapter(RequestCallback requestCallback) { - this.adaptee = requestCallback; - } - - @Override - public void doWithRequest(final org.springframework.http.client.AsyncClientHttpRequest request) - throws IOException { - - this.adaptee.doWithRequest(new ClientHttpRequest() { - @Override - public ClientHttpResponse execute() throws IOException { - throw new UnsupportedOperationException("execute not supported"); - } - @Override - public OutputStream getBody() throws IOException { - return request.getBody(); - } - @Override - @Nullable - public HttpMethod getMethod() { - return request.getMethod(); - } - @Override - public String getMethodValue() { - return request.getMethodValue(); - } - @Override - public URI getURI() { - return request.getURI(); - } - @Override - public HttpHeaders getHeaders() { - return request.getHeaders(); - } - }); - } - } - -} diff --git a/spring-web/src/test/java/org/springframework/http/client/AbstractAsyncHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/AbstractAsyncHttpRequestFactoryTests.java deleted file mode 100644 index 4ae702d551..0000000000 --- a/spring-web/src/test/java/org/springframework/http/client/AbstractAsyncHttpRequestFactoryTests.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2002-2020 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.http.client; - -import java.io.IOException; -import java.net.URI; -import java.util.Arrays; -import java.util.Locale; -import java.util.concurrent.Future; - -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.StreamingHttpOutputMessage; -import org.springframework.util.FileCopyUtils; -import org.springframework.util.StreamUtils; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.ListenableFutureCallback; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; - -@SuppressWarnings("deprecation") -public abstract class AbstractAsyncHttpRequestFactoryTests extends AbstractMockWebServerTests { - - protected AsyncClientHttpRequestFactory factory; - - - @BeforeEach - public final void createFactory() throws Exception { - this.factory = createRequestFactory(); - if (this.factory instanceof InitializingBean) { - ((InitializingBean) this.factory).afterPropertiesSet(); - } - } - - @AfterEach - public final void destroyFactory() throws Exception { - if (this.factory instanceof DisposableBean) { - ((DisposableBean) this.factory).destroy(); - } - } - - protected abstract AsyncClientHttpRequestFactory createRequestFactory(); - - - @Test - public void status() throws Exception { - URI uri = new URI(baseUrl + "/status/notfound"); - AsyncClientHttpRequest request = this.factory.createAsyncRequest(uri, HttpMethod.GET); - assertThat(request.getMethod()).as("Invalid HTTP method").isEqualTo(HttpMethod.GET); - assertThat(request.getURI()).as("Invalid HTTP URI").isEqualTo(uri); - Future futureResponse = request.executeAsync(); - try (ClientHttpResponse response = futureResponse.get()) { - assertThat(response.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.NOT_FOUND); - } - } - - @Test - public void statusCallback() throws Exception { - URI uri = new URI(baseUrl + "/status/notfound"); - AsyncClientHttpRequest request = this.factory.createAsyncRequest(uri, HttpMethod.GET); - assertThat(request.getMethod()).as("Invalid HTTP method").isEqualTo(HttpMethod.GET); - assertThat(request.getURI()).as("Invalid HTTP URI").isEqualTo(uri); - ListenableFuture listenableFuture = request.executeAsync(); - listenableFuture.addCallback(new ListenableFutureCallback() { - @Override - public void onSuccess(ClientHttpResponse result) { - try { - assertThat(result.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.NOT_FOUND); - } - catch (IOException ex) { - throw new AssertionError(ex.getMessage(), ex); - } - } - @Override - public void onFailure(Throwable ex) { - throw new AssertionError(ex.getMessage(), ex); - } - }); - try (ClientHttpResponse response = listenableFuture.get()) { - assertThat(response.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.NOT_FOUND); - } - } - - @Test - public void echo() throws Exception { - AsyncClientHttpRequest request = this.factory.createAsyncRequest(new URI(baseUrl + "/echo"), HttpMethod.PUT); - assertThat(request.getMethod()).as("Invalid HTTP method").isEqualTo(HttpMethod.PUT); - String headerName = "MyHeader"; - String headerValue1 = "value1"; - request.getHeaders().add(headerName, headerValue1); - String headerValue2 = "value2"; - request.getHeaders().add(headerName, headerValue2); - final byte[] body = "Hello World".getBytes("UTF-8"); - request.getHeaders().setContentLength(body.length); - - if (request instanceof StreamingHttpOutputMessage) { - StreamingHttpOutputMessage streamingRequest = (StreamingHttpOutputMessage) request; - streamingRequest.setBody(outputStream -> StreamUtils.copy(body, outputStream)); - } - else { - StreamUtils.copy(body, request.getBody()); - } - - Future futureResponse = request.executeAsync(); - try ( ClientHttpResponse response = futureResponse.get()) { - assertThat(response.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.OK); - assertThat(response.getHeaders().containsKey(headerName)).as("Header not found").isTrue(); - assertThat(response.getHeaders().get(headerName)).as("Header value not found").isEqualTo(Arrays.asList(headerValue1, headerValue2)); - byte[] result = FileCopyUtils.copyToByteArray(response.getBody()); - assertThat(Arrays.equals(body, result)).as("Invalid body").isTrue(); - } - } - - @Test - public void multipleWrites() throws Exception { - AsyncClientHttpRequest request = this.factory.createAsyncRequest(new URI(baseUrl + "/echo"), HttpMethod.POST); - final byte[] body = "Hello World".getBytes("UTF-8"); - - if (request instanceof StreamingHttpOutputMessage) { - StreamingHttpOutputMessage streamingRequest = (StreamingHttpOutputMessage) request; - streamingRequest.setBody(outputStream -> StreamUtils.copy(body, outputStream)); - } - else { - StreamUtils.copy(body, request.getBody()); - } - - Future futureResponse = request.executeAsync(); - try (ClientHttpResponse response = futureResponse.get()) { - assertThat(response).isNotNull(); - assertThatIllegalStateException().isThrownBy(() -> FileCopyUtils.copy(body, request.getBody())); - } - } - - @Test - public void headersAfterExecute() throws Exception { - AsyncClientHttpRequest request = this.factory.createAsyncRequest(new URI(baseUrl + "/echo"), HttpMethod.POST); - request.getHeaders().add("MyHeader", "value"); - byte[] body = "Hello World".getBytes("UTF-8"); - FileCopyUtils.copy(body, request.getBody()); - - Future futureResponse = request.executeAsync(); - try (ClientHttpResponse response = futureResponse.get()) { - assertThat(response).isNotNull(); - assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> - request.getHeaders().add("MyHeader", "value")); - } - } - - @Test - public void httpMethods() throws Exception { - assertHttpMethod("get", HttpMethod.GET); - assertHttpMethod("head", HttpMethod.HEAD); - assertHttpMethod("post", HttpMethod.POST); - assertHttpMethod("put", HttpMethod.PUT); - assertHttpMethod("options", HttpMethod.OPTIONS); - assertHttpMethod("delete", HttpMethod.DELETE); - } - - protected void assertHttpMethod(String path, HttpMethod method) throws Exception { - AsyncClientHttpRequest request = this.factory.createAsyncRequest(new URI(baseUrl + "/methods/" + path), method); - if (method == HttpMethod.POST || method == HttpMethod.PUT || method == HttpMethod.PATCH) { - // requires a body - request.getBody().write(32); - } - Future futureResponse = request.executeAsync(); - try (ClientHttpResponse response = futureResponse.get()) { - assertThat(response.getStatusCode()).as("Invalid response status").isEqualTo(HttpStatus.OK); - assertThat(request.getMethod().name()).as("Invalid method").isEqualTo(path.toUpperCase(Locale.ENGLISH)); - } - } - - @Test - public void cancel() throws Exception { - URI uri = new URI(baseUrl + "/status/notfound"); - AsyncClientHttpRequest request = this.factory.createAsyncRequest(uri, HttpMethod.GET); - Future futureResponse = request.executeAsync(); - futureResponse.cancel(true); - assertThat(futureResponse.isCancelled()).isTrue(); - } - -} diff --git a/spring-web/src/test/java/org/springframework/http/client/BufferedSimpleAsyncHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/BufferedSimpleAsyncHttpRequestFactoryTests.java deleted file mode 100644 index f019ddd797..0000000000 --- a/spring-web/src/test/java/org/springframework/http/client/BufferedSimpleAsyncHttpRequestFactoryTests.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2002-2013 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.http.client; - -import java.net.ProtocolException; - -import org.junit.jupiter.api.Test; - -import org.springframework.core.task.AsyncListenableTaskExecutor; -import org.springframework.core.task.SimpleAsyncTaskExecutor; -import org.springframework.http.HttpMethod; - -public class BufferedSimpleAsyncHttpRequestFactoryTests extends AbstractAsyncHttpRequestFactoryTests { - - @SuppressWarnings("deprecation") - @Override - protected AsyncClientHttpRequestFactory createRequestFactory() { - SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); - AsyncListenableTaskExecutor taskExecutor = new SimpleAsyncTaskExecutor(); - requestFactory.setTaskExecutor(taskExecutor); - return requestFactory; - } - - @Override - @Test - public void httpMethods() throws Exception { - super.httpMethods(); - try { - assertHttpMethod("patch", HttpMethod.PATCH); - } - catch (ProtocolException ex) { - // Currently HttpURLConnection does not support HTTP PATCH - } - } - -} diff --git a/spring-web/src/test/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactoryTests.java deleted file mode 100644 index 7ae09ce869..0000000000 --- a/spring-web/src/test/java/org/springframework/http/client/HttpComponentsAsyncClientHttpRequestFactoryTests.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2002-2019 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.http.client; - -import java.net.URI; - -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.protocol.HttpClientContext; -import org.apache.http.impl.nio.client.CloseableHttpAsyncClient; -import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; -import org.junit.jupiter.api.Test; - -import org.springframework.http.HttpMethod; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author Arjen Poutsma - * @author Stephane Nicoll - */ -@SuppressWarnings("deprecation") -public class HttpComponentsAsyncClientHttpRequestFactoryTests extends AbstractAsyncHttpRequestFactoryTests { - - @Override - protected AsyncClientHttpRequestFactory createRequestFactory() { - return new HttpComponentsAsyncClientHttpRequestFactory(); - } - - - @Override - @Test - public void httpMethods() throws Exception { - super.httpMethods(); - assertHttpMethod("patch", HttpMethod.PATCH); - } - - @Test - public void customHttpAsyncClientUsesItsDefault() throws Exception { - HttpComponentsAsyncClientHttpRequestFactory factory = - new HttpComponentsAsyncClientHttpRequestFactory(); - - URI uri = new URI(baseUrl + "/status/ok"); - HttpComponentsAsyncClientHttpRequest request = (HttpComponentsAsyncClientHttpRequest) - factory.createAsyncRequest(uri, HttpMethod.GET); - - assertThat(request.getHttpContext().getAttribute(HttpClientContext.REQUEST_CONFIG)).as("No custom config should be set with a custom HttpAsyncClient").isNull(); - } - - @Test - public void defaultSettingsOfHttpAsyncClientLostOnExecutorCustomization() throws Exception { - CloseableHttpAsyncClient client = HttpAsyncClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom().setConnectTimeout(1234).build()) - .build(); - HttpComponentsAsyncClientHttpRequestFactory factory = new HttpComponentsAsyncClientHttpRequestFactory(client); - - URI uri = new URI(baseUrl + "/status/ok"); - HttpComponentsAsyncClientHttpRequest request = (HttpComponentsAsyncClientHttpRequest) - factory.createAsyncRequest(uri, HttpMethod.GET); - - assertThat(request.getHttpContext().getAttribute(HttpClientContext.REQUEST_CONFIG)).as("No custom config should be set with a custom HttpClient").isNull(); - - factory.setConnectionRequestTimeout(4567); - HttpComponentsAsyncClientHttpRequest request2 = (HttpComponentsAsyncClientHttpRequest) - factory.createAsyncRequest(uri, HttpMethod.GET); - Object requestConfigAttribute = request2.getHttpContext().getAttribute(HttpClientContext.REQUEST_CONFIG); - assertThat(requestConfigAttribute).isNotNull(); - RequestConfig requestConfig = (RequestConfig) requestConfigAttribute; - - assertThat(requestConfig.getConnectionRequestTimeout()).isEqualTo(4567); - // No way to access the request config of the HTTP client so no way to "merge" our customizations - assertThat(requestConfig.getConnectTimeout()).isEqualTo(-1); - } - -} diff --git a/spring-web/src/test/java/org/springframework/http/client/Netty4AsyncClientHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/Netty4AsyncClientHttpRequestFactoryTests.java deleted file mode 100644 index 87ed2ae399..0000000000 --- a/spring-web/src/test/java/org/springframework/http/client/Netty4AsyncClientHttpRequestFactoryTests.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2019 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.http.client; - -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import org.springframework.http.HttpMethod; - -/** - * @author Arjen Poutsma - */ -public class Netty4AsyncClientHttpRequestFactoryTests extends AbstractAsyncHttpRequestFactoryTests { - - private static EventLoopGroup eventLoopGroup; - - - @BeforeAll - public static void createEventLoopGroup() { - eventLoopGroup = new NioEventLoopGroup(); - } - - @AfterAll - public static void shutdownEventLoopGroup() throws InterruptedException { - eventLoopGroup.shutdownGracefully().sync(); - } - - @SuppressWarnings("deprecation") - @Override - protected AsyncClientHttpRequestFactory createRequestFactory() { - return new Netty4ClientHttpRequestFactory(eventLoopGroup); - } - - @Override - @Test - public void httpMethods() throws Exception { - super.httpMethods(); - assertHttpMethod("patch", HttpMethod.PATCH); - } - -} diff --git a/spring-web/src/test/java/org/springframework/http/client/Netty4ClientHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/Netty4ClientHttpRequestFactoryTests.java deleted file mode 100644 index bfc087f848..0000000000 --- a/spring-web/src/test/java/org/springframework/http/client/Netty4ClientHttpRequestFactoryTests.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2019 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.http.client; - -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import org.springframework.http.HttpMethod; - -/** - * @author Arjen Poutsma - */ -public class Netty4ClientHttpRequestFactoryTests extends AbstractHttpRequestFactoryTests { - - private static EventLoopGroup eventLoopGroup; - - - @BeforeAll - public static void createEventLoopGroup() { - eventLoopGroup = new NioEventLoopGroup(); - } - - @AfterAll - public static void shutdownEventLoopGroup() throws InterruptedException { - eventLoopGroup.shutdownGracefully().sync(); - } - - @Override - @SuppressWarnings("deprecation") - protected ClientHttpRequestFactory createRequestFactory() { - return new Netty4ClientHttpRequestFactory(eventLoopGroup); - } - - @Override - @Test - public void httpMethods() throws Exception { - super.httpMethods(); - assertHttpMethod("patch", HttpMethod.PATCH); - } - -} diff --git a/spring-web/src/test/java/org/springframework/http/client/OkHttp3AsyncClientHttpRequestFactoryTests.java b/spring-web/src/test/java/org/springframework/http/client/OkHttp3AsyncClientHttpRequestFactoryTests.java deleted file mode 100644 index 541b7bd693..0000000000 --- a/spring-web/src/test/java/org/springframework/http/client/OkHttp3AsyncClientHttpRequestFactoryTests.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2016 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.http.client; - -import org.junit.jupiter.api.Test; - -import org.springframework.http.HttpMethod; - -/** - * @author Roy Clarkson - */ -public class OkHttp3AsyncClientHttpRequestFactoryTests extends AbstractAsyncHttpRequestFactoryTests { - - @SuppressWarnings("deprecation") - @Override - protected AsyncClientHttpRequestFactory createRequestFactory() { - return new OkHttp3ClientHttpRequestFactory(); - } - - @Override - @Test - public void httpMethods() throws Exception { - super.httpMethods(); - assertHttpMethod("patch", HttpMethod.PATCH); - } - -} diff --git a/spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java b/spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java deleted file mode 100644 index 245172958b..0000000000 --- a/spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright 2002-2019 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.web.client; - -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.Collections; -import java.util.EnumSet; -import java.util.Set; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; - -import org.junit.jupiter.api.Test; - -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpRequest; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; -import org.springframework.http.ResponseEntity; -import org.springframework.http.client.ClientHttpResponse; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; -import org.springframework.util.concurrent.ListenableFuture; -import org.springframework.util.concurrent.ListenableFutureCallback; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.assertj.core.api.Assertions.fail; - -/** - * Integration tests for {@link AsyncRestTemplate}. - * - *

Logging configuration for {@code MockWebServer}

- * - *

In order for our log4j2 configuration to be used in an IDE, you must - * set the following system property before running any tests — for - * example, in Run Configurations in Eclipse. - * - *

- * -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager
- * 
- * - * @author Arjen Poutsma - * @author Sebastien Deleuze - */ -@SuppressWarnings("deprecation") -public class AsyncRestTemplateIntegrationTests extends AbstractMockWebServerTests { - - private final AsyncRestTemplate template = new AsyncRestTemplate( - new org.springframework.http.client.HttpComponentsAsyncClientHttpRequestFactory()); - - - @Test - public void getEntity() throws Exception { - Future> future = template.getForEntity(baseUrl + "/{method}", String.class, "get"); - ResponseEntity entity = future.get(); - assertThat(entity.getBody()).as("Invalid content").isEqualTo(helloWorld); - assertThat(entity.getHeaders().isEmpty()).as("No headers").isFalse(); - assertThat(entity.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(textContentType); - assertThat(entity.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.OK); - } - - @Test - public void getEntityFromCompletable() throws Exception { - ListenableFuture> future = template.getForEntity(baseUrl + "/{method}", String.class, "get"); - ResponseEntity entity = future.completable().get(); - assertThat(entity.getBody()).as("Invalid content").isEqualTo(helloWorld); - assertThat(entity.getHeaders().isEmpty()).as("No headers").isFalse(); - assertThat(entity.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(textContentType); - assertThat(entity.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.OK); - } - - @Test - public void multipleFutureGets() throws Exception { - Future> future = template.getForEntity(baseUrl + "/{method}", String.class, "get"); - future.get(); - future.get(); - } - - @Test - public void getEntityCallback() throws Exception { - ListenableFuture> futureEntity = - template.getForEntity(baseUrl + "/{method}", String.class, "get"); - futureEntity.addCallback(new ListenableFutureCallback>() { - @Override - public void onSuccess(ResponseEntity entity) { - assertThat(entity.getBody()).as("Invalid content").isEqualTo(helloWorld); - assertThat(entity.getHeaders().isEmpty()).as("No headers").isFalse(); - assertThat(entity.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(textContentType); - assertThat(entity.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.OK); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(futureEntity); - } - - @Test - public void getEntityCallbackWithLambdas() throws Exception { - ListenableFuture> futureEntity = - template.getForEntity(baseUrl + "/{method}", String.class, "get"); - futureEntity.addCallback(entity -> { - assertThat(entity.getBody()).as("Invalid content").isEqualTo(helloWorld); - assertThat(entity.getHeaders().isEmpty()).as("No headers").isFalse(); - assertThat(entity.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(textContentType); - assertThat(entity.getStatusCode()).as("Invalid status code").isEqualTo(HttpStatus.OK); - }, ex -> fail(ex.getMessage())); - waitTillDone(futureEntity); - } - - @Test - public void getNoResponse() throws Exception { - Future> futureEntity = template.getForEntity(baseUrl + "/get/nothing", String.class); - ResponseEntity entity = futureEntity.get(); - assertThat(entity.getBody()).as("Invalid content").isNull(); - } - - @Test - public void getNoContentTypeHeader() throws Exception { - Future> futureEntity = template.getForEntity(baseUrl + "/get/nocontenttype", byte[].class); - ResponseEntity responseEntity = futureEntity.get(); - assertThat(responseEntity.getBody()).as("Invalid content").isEqualTo(helloWorld.getBytes("UTF-8")); - } - - @Test - public void getNoContent() throws Exception { - Future> responseFuture = template.getForEntity(baseUrl + "/status/nocontent", String.class); - ResponseEntity entity = responseFuture.get(); - assertThat(entity.getStatusCode()).as("Invalid response code").isEqualTo(HttpStatus.NO_CONTENT); - assertThat(entity.getBody()).as("Invalid content").isNull(); - } - - @Test - public void getNotModified() throws Exception { - Future> responseFuture = template.getForEntity(baseUrl + "/status/notmodified", String.class); - ResponseEntity entity = responseFuture.get(); - assertThat(entity.getStatusCode()).as("Invalid response code").isEqualTo(HttpStatus.NOT_MODIFIED); - assertThat(entity.getBody()).as("Invalid content").isNull(); - } - - @Test - public void headForHeaders() throws Exception { - Future headersFuture = template.headForHeaders(baseUrl + "/get"); - HttpHeaders headers = headersFuture.get(); - assertThat(headers.containsKey("Content-Type")).as("No Content-Type header").isTrue(); - } - - @Test - public void headForHeadersCallback() throws Exception { - ListenableFuture headersFuture = template.headForHeaders(baseUrl + "/get"); - headersFuture.addCallback(new ListenableFutureCallback() { - @Override - public void onSuccess(HttpHeaders result) { - assertThat(result.containsKey("Content-Type")).as("No Content-Type header").isTrue(); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(headersFuture); - } - - @Test - public void headForHeadersCallbackWithLambdas() throws Exception { - ListenableFuture headersFuture = template.headForHeaders(baseUrl + "/get"); - headersFuture.addCallback(result -> assertThat(result.containsKey("Content-Type")).as("No Content-Type header").isTrue(), ex -> fail(ex.getMessage())); - waitTillDone(headersFuture); - } - - @Test - public void postForLocation() throws Exception { - HttpHeaders entityHeaders = new HttpHeaders(); - entityHeaders.setContentType(new MediaType("text", "plain", StandardCharsets.ISO_8859_1)); - HttpEntity entity = new HttpEntity<>(helloWorld, entityHeaders); - Future locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post"); - URI location = locationFuture.get(); - assertThat(location).as("Invalid location").isEqualTo(new URI(baseUrl + "/post/1")); - } - - @Test - public void postForLocationCallback() throws Exception { - HttpHeaders entityHeaders = new HttpHeaders(); - entityHeaders.setContentType(new MediaType("text", "plain", StandardCharsets.ISO_8859_1)); - HttpEntity entity = new HttpEntity<>(helloWorld, entityHeaders); - final URI expected = new URI(baseUrl + "/post/1"); - ListenableFuture locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post"); - locationFuture.addCallback(new ListenableFutureCallback() { - @Override - public void onSuccess(URI result) { - assertThat(result).as("Invalid location").isEqualTo(expected); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(locationFuture); - } - - @Test - public void postForLocationCallbackWithLambdas() throws Exception { - HttpHeaders entityHeaders = new HttpHeaders(); - entityHeaders.setContentType(new MediaType("text", "plain", StandardCharsets.ISO_8859_1)); - HttpEntity entity = new HttpEntity<>(helloWorld, entityHeaders); - final URI expected = new URI(baseUrl + "/post/1"); - ListenableFuture locationFuture = template.postForLocation(baseUrl + "/{method}", entity, "post"); - locationFuture.addCallback(result -> assertThat(result).as("Invalid location").isEqualTo(expected), - ex -> fail(ex.getMessage())); - waitTillDone(locationFuture); - } - - @Test - public void postForEntity() throws Exception { - HttpEntity requestEntity = new HttpEntity<>(helloWorld); - Future> responseEntityFuture = - template.postForEntity(baseUrl + "/{method}", requestEntity, String.class, "post"); - ResponseEntity responseEntity = responseEntityFuture.get(); - assertThat(responseEntity.getBody()).as("Invalid content").isEqualTo(helloWorld); - } - - @Test - public void postForEntityCallback() throws Exception { - HttpEntity requestEntity = new HttpEntity<>(helloWorld); - ListenableFuture> responseEntityFuture = - template.postForEntity(baseUrl + "/{method}", requestEntity, String.class, "post"); - responseEntityFuture.addCallback(new ListenableFutureCallback>() { - @Override - public void onSuccess(ResponseEntity result) { - assertThat(result.getBody()).as("Invalid content").isEqualTo(helloWorld); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(responseEntityFuture); - } - - @Test - public void postForEntityCallbackWithLambdas() throws Exception { - HttpEntity requestEntity = new HttpEntity<>(helloWorld); - ListenableFuture> responseEntityFuture = - template.postForEntity(baseUrl + "/{method}", requestEntity, String.class, "post"); - responseEntityFuture.addCallback( - result -> assertThat(result.getBody()).as("Invalid content").isEqualTo(helloWorld), - ex -> fail(ex.getMessage())); - waitTillDone(responseEntityFuture); - } - - @Test - public void put() throws Exception { - HttpEntity requestEntity = new HttpEntity<>(helloWorld); - Future responseEntityFuture = template.put(baseUrl + "/{method}", requestEntity, "put"); - responseEntityFuture.get(); - } - - @Test - public void putCallback() throws Exception { - HttpEntity requestEntity = new HttpEntity<>(helloWorld); - ListenableFuture responseEntityFuture = template.put(baseUrl + "/{method}", requestEntity, "put"); - responseEntityFuture.addCallback(new ListenableFutureCallback() { - @Override - public void onSuccess(Object result) { - assertThat(result).isNull(); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(responseEntityFuture); - } - - @Test - public void delete() throws Exception { - Future deletedFuture = template.delete(new URI(baseUrl + "/delete")); - deletedFuture.get(); - } - - @Test - public void deleteCallback() throws Exception { - ListenableFuture deletedFuture = template.delete(new URI(baseUrl + "/delete")); - deletedFuture.addCallback(new ListenableFutureCallback() { - @Override - public void onSuccess(Object result) { - assertThat(result).isNull(); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(deletedFuture); - } - - @Test - public void deleteCallbackWithLambdas() throws Exception { - ListenableFuture deletedFuture = template.delete(new URI(baseUrl + "/delete")); - deletedFuture.addCallback(result -> assertThat(result).isNull(), ex -> fail(ex.getMessage())); - waitTillDone(deletedFuture); - } - - @Test - public void identicalExceptionThroughGetAndCallback() throws Exception { - final HttpClientErrorException[] callbackException = new HttpClientErrorException[1]; - - final CountDownLatch latch = new CountDownLatch(1); - ListenableFuture future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null); - future.addCallback(new ListenableFutureCallback() { - @Override - public void onSuccess(Object result) { - fail("onSuccess not expected"); - } - @Override - public void onFailure(Throwable ex) { - boolean condition = ex instanceof HttpClientErrorException; - assertThat(condition).isTrue(); - callbackException[0] = (HttpClientErrorException) ex; - latch.countDown(); - } - }); - - try { - future.get(); - fail("Exception expected"); - } - catch (ExecutionException ex) { - Throwable cause = ex.getCause(); - boolean condition = cause instanceof HttpClientErrorException; - assertThat(condition).isTrue(); - latch.await(5, TimeUnit.SECONDS); - assertThat(cause).isSameAs(callbackException[0]); - } - } - - @Test - public void notFoundGet() throws Exception { - assertThatExceptionOfType(ExecutionException.class).isThrownBy(() -> { - Future future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null); - future.get(); - }) - .withCauseInstanceOf(HttpClientErrorException.class) - .satisfies(ex -> { - HttpClientErrorException cause = (HttpClientErrorException) ex.getCause(); - assertThat(cause.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - assertThat(cause.getStatusText()).isNotNull(); - assertThat(cause.getResponseBodyAsString()).isNotNull(); - }); - } - - @Test - public void notFoundCallback() throws Exception { - ListenableFuture future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null); - future.addCallback(new ListenableFutureCallback() { - @Override - public void onSuccess(Object result) { - fail("onSuccess not expected"); - } - @Override - public void onFailure(Throwable t) { - boolean condition = t instanceof HttpClientErrorException; - assertThat(condition).isTrue(); - HttpClientErrorException ex = (HttpClientErrorException) t; - assertThat(ex.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - assertThat(ex.getStatusText()).isNotNull(); - assertThat(ex.getResponseBodyAsString()).isNotNull(); - } - }); - waitTillDone(future); - } - - @Test - public void notFoundCallbackWithLambdas() throws Exception { - ListenableFuture future = template.execute(baseUrl + "/status/notfound", HttpMethod.GET, null, null); - future.addCallback(result -> fail("onSuccess not expected"), ex -> { - boolean condition = ex instanceof HttpClientErrorException; - assertThat(condition).isTrue(); - HttpClientErrorException hcex = (HttpClientErrorException) ex; - assertThat(hcex.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - assertThat(hcex.getStatusText()).isNotNull(); - assertThat(hcex.getResponseBodyAsString()).isNotNull(); - }); - waitTillDone(future); - } - - @Test - public void serverError() throws Exception { - try { - Future future = template.execute(baseUrl + "/status/server", HttpMethod.GET, null, null); - future.get(); - fail("HttpServerErrorException expected"); - } - catch (ExecutionException ex) { - boolean condition = ex.getCause() instanceof HttpServerErrorException; - assertThat(condition).isTrue(); - HttpServerErrorException cause = (HttpServerErrorException)ex.getCause(); - - assertThat(cause.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - assertThat(cause.getStatusText()).isNotNull(); - assertThat(cause.getResponseBodyAsString()).isNotNull(); - } - } - - @Test - public void serverErrorCallback() throws Exception { - ListenableFuture future = template.execute(baseUrl + "/status/server", HttpMethod.GET, null, null); - future.addCallback(new ListenableFutureCallback() { - @Override - public void onSuccess(Void result) { - fail("onSuccess not expected"); - } - @Override - public void onFailure(Throwable ex) { - boolean condition = ex instanceof HttpServerErrorException; - assertThat(condition).isTrue(); - HttpServerErrorException hsex = (HttpServerErrorException) ex; - assertThat(hsex.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - assertThat(hsex.getStatusText()).isNotNull(); - assertThat(hsex.getResponseBodyAsString()).isNotNull(); - } - }); - waitTillDone(future); - } - - @Test - public void serverErrorCallbackWithLambdas() throws Exception { - ListenableFuture future = template.execute(baseUrl + "/status/server", HttpMethod.GET, null, null); - future.addCallback(result -> fail("onSuccess not expected"), ex -> { - boolean condition = ex instanceof HttpServerErrorException; - assertThat(condition).isTrue(); - HttpServerErrorException hsex = (HttpServerErrorException) ex; - assertThat(hsex.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - assertThat(hsex.getStatusText()).isNotNull(); - assertThat(hsex.getResponseBodyAsString()).isNotNull(); - }); - waitTillDone(future); - } - - @Test - public void optionsForAllow() throws Exception { - Future> allowedFuture = template.optionsForAllow(new URI(baseUrl + "/get")); - Set allowed = allowedFuture.get(); - assertThat(allowed).as("Invalid response").isEqualTo(EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD, HttpMethod.TRACE)); - } - - @Test - public void optionsForAllowCallback() throws Exception { - ListenableFuture> allowedFuture = template.optionsForAllow(new URI(baseUrl + "/get")); - allowedFuture.addCallback(new ListenableFutureCallback>() { - @Override - public void onSuccess(Set result) { - assertThat(result).as("Invalid response").isEqualTo(EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, - HttpMethod.HEAD, HttpMethod.TRACE)); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(allowedFuture); - } - - @Test - public void optionsForAllowCallbackWithLambdas() throws Exception{ - ListenableFuture> allowedFuture = template.optionsForAllow(new URI(baseUrl + "/get")); - allowedFuture.addCallback(result -> assertThat(result).as("Invalid response").isEqualTo(EnumSet.of(HttpMethod.GET, HttpMethod.OPTIONS, HttpMethod.HEAD,HttpMethod.TRACE)), - ex -> fail(ex.getMessage())); - waitTillDone(allowedFuture); - } - - @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void exchangeGet() throws Exception { - HttpHeaders requestHeaders = new HttpHeaders(); - requestHeaders.set("MyHeader", "MyValue"); - HttpEntity requestEntity = new HttpEntity(requestHeaders); - Future> responseFuture = - template.exchange(baseUrl + "/{method}", HttpMethod.GET, requestEntity, String.class, "get"); - ResponseEntity response = responseFuture.get(); - assertThat(response.getBody()).as("Invalid content").isEqualTo(helloWorld); - } - - @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void exchangeGetCallback() throws Exception { - HttpHeaders requestHeaders = new HttpHeaders(); - requestHeaders.set("MyHeader", "MyValue"); - HttpEntity requestEntity = new HttpEntity(requestHeaders); - ListenableFuture> responseFuture = - template.exchange(baseUrl + "/{method}", HttpMethod.GET, requestEntity, String.class, "get"); - responseFuture.addCallback(new ListenableFutureCallback>() { - @Override - public void onSuccess(ResponseEntity result) { - assertThat(result.getBody()).as("Invalid content").isEqualTo(helloWorld); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(responseFuture); - } - - @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void exchangeGetCallbackWithLambdas() throws Exception { - HttpHeaders requestHeaders = new HttpHeaders(); - requestHeaders.set("MyHeader", "MyValue"); - HttpEntity requestEntity = new HttpEntity(requestHeaders); - ListenableFuture> responseFuture = - template.exchange(baseUrl + "/{method}", HttpMethod.GET, requestEntity, String.class, "get"); - responseFuture.addCallback(result -> assertThat(result.getBody()).as("Invalid content").isEqualTo(helloWorld), ex -> fail(ex.getMessage())); - waitTillDone(responseFuture); - } - - @Test - public void exchangePost() throws Exception { - HttpHeaders requestHeaders = new HttpHeaders(); - requestHeaders.set("MyHeader", "MyValue"); - requestHeaders.setContentType(MediaType.TEXT_PLAIN); - HttpEntity requestEntity = new HttpEntity<>(helloWorld, requestHeaders); - Future> resultFuture = - template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post"); - ResponseEntity result = resultFuture.get(); - assertThat(result.getHeaders().getLocation()).as("Invalid location").isEqualTo(new URI(baseUrl + "/post/1")); - assertThat(result.hasBody()).isFalse(); - } - - @Test - public void exchangePostCallback() throws Exception { - HttpHeaders requestHeaders = new HttpHeaders(); - requestHeaders.set("MyHeader", "MyValue"); - requestHeaders.setContentType(MediaType.TEXT_PLAIN); - HttpEntity requestEntity = new HttpEntity<>(helloWorld, requestHeaders); - ListenableFuture> resultFuture = - template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post"); - final URI expected =new URI(baseUrl + "/post/1"); - resultFuture.addCallback(new ListenableFutureCallback>() { - @Override - public void onSuccess(ResponseEntity result) { - assertThat(result.getHeaders().getLocation()).as("Invalid location").isEqualTo(expected); - assertThat(result.hasBody()).isFalse(); - } - @Override - public void onFailure(Throwable ex) { - fail(ex.getMessage()); - } - }); - waitTillDone(resultFuture); - } - - @Test - public void exchangePostCallbackWithLambdas() throws Exception { - HttpHeaders requestHeaders = new HttpHeaders(); - requestHeaders.set("MyHeader", "MyValue"); - requestHeaders.setContentType(MediaType.TEXT_PLAIN); - HttpEntity requestEntity = new HttpEntity<>(helloWorld, requestHeaders); - ListenableFuture> resultFuture = - template.exchange(baseUrl + "/{method}", HttpMethod.POST, requestEntity, Void.class, "post"); - final URI expected =new URI(baseUrl + "/post/1"); - resultFuture.addCallback(result -> { - assertThat(result.getHeaders().getLocation()).as("Invalid location").isEqualTo(expected); - assertThat(result.hasBody()).isFalse(); - }, ex -> fail(ex.getMessage())); - waitTillDone(resultFuture); - } - - @Test - public void multipartFormData() throws Exception { - MultiValueMap parts = new LinkedMultiValueMap<>(); - parts.add("name 1", "value 1"); - parts.add("name 2", "value 2+1"); - parts.add("name 2", "value 2+2"); - Resource logo = new ClassPathResource("/org/springframework/http/converter/logo.jpg"); - parts.add("logo", logo); - - HttpEntity> requestBody = new HttpEntity<>(parts); - Future future = template.postForLocation(baseUrl + "/multipartFormData", requestBody); - future.get(); - } - - @Test - public void getAndInterceptResponse() throws Exception { - RequestInterceptor interceptor = new RequestInterceptor(); - template.setInterceptors(Collections.singletonList(interceptor)); - ListenableFuture> future = template.getForEntity(baseUrl + "/get", String.class); - - interceptor.latch.await(5, TimeUnit.SECONDS); - assertThat(interceptor.response).isNotNull(); - assertThat(interceptor.response.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(interceptor.exception).isNull(); - assertThat(future.get().getBody()).isEqualTo(helloWorld); - } - - @Test - public void getAndInterceptError() throws Exception { - RequestInterceptor interceptor = new RequestInterceptor(); - template.setInterceptors(Collections.singletonList(interceptor)); - template.getForEntity(baseUrl + "/status/notfound", String.class); - - interceptor.latch.await(5, TimeUnit.SECONDS); - assertThat(interceptor.response).isNotNull(); - assertThat(interceptor.response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - assertThat(interceptor.exception).isNull(); - } - - private void waitTillDone(ListenableFuture future) { - while (!future.isDone()) { - try { - Thread.sleep(5); - } - catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - } - } - } - - - private static class RequestInterceptor implements org.springframework.http.client.AsyncClientHttpRequestInterceptor { - - private final CountDownLatch latch = new CountDownLatch(1); - - private volatile ClientHttpResponse response; - - private volatile Throwable exception; - - @Override - public ListenableFuture intercept(HttpRequest request, byte[] body, - org.springframework.http.client.AsyncClientHttpRequestExecution execution) throws IOException { - - ListenableFuture future = execution.executeAsync(request, body); - future.addCallback( - resp -> { - response = resp; - this.latch.countDown(); - }, - ex -> { - exception = ex; - this.latch.countDown(); - }); - return future; - } - } - -} diff --git a/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java b/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java index f53cf890c7..cc684fe001 100644 --- a/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java +++ b/spring-web/src/test/java/org/springframework/web/client/RestTemplateIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2021 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. @@ -92,7 +92,6 @@ class RestTemplateIntegrationTests extends AbstractMockWebServerTests { return Stream.of( new SimpleClientHttpRequestFactory(), new HttpComponentsClientHttpRequestFactory(), - new org.springframework.http.client.Netty4ClientHttpRequestFactory(), new OkHttp3ClientHttpRequestFactory() ); } diff --git a/src/docs/asciidoc/integration.adoc b/src/docs/asciidoc/integration.adoc index c299efbe5e..c895bb9c5a 100644 --- a/src/docs/asciidoc/integration.adoc +++ b/src/docs/asciidoc/integration.adoc @@ -344,13 +344,6 @@ to `multipart/form-data` by the `FormHttpMessageConverter`. If the `MultiValueMa If necessary the `Content-Type` may also be set explicitly. -[[rest-async-resttemplate]] -=== Using `AsyncRestTemplate` (Deprecated) - -The `AsyncRestTemplate` is deprecated. For all use cases where you might consider using -`AsyncRestTemplate`, use the <> instead. - - [[remoting]] == Remoting and Web Services