diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java
index 608d17084a..a36077f248 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientRequest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -30,12 +30,12 @@ import org.springframework.web.reactive.function.BodyInserter;
/**
* Represents a typed, immutable, client-side HTTP request, as executed by the
- * {@link WebClient}. Instances of this interface can be created via static
- * builder methods in this class.
+ * {@link ExchangeFunction}. Instances of this interface can be created via static
+ * builder methods.
*
*
Note that applications are more likely to perform requests through
- * {@link WebClientOperations} rather than using this directly.
- * :
+ * {@link WebClient} rather than using this directly.
+ *
* @param the type of the body that this request contains
* @author Brian Clozel
* @author Arjen Poutsma
@@ -75,7 +75,7 @@ public interface ClientRequest {
* @param strategies the strategies to use when writing
* @return {@code Mono} to indicate when writing is complete
*/
- Mono writeTo(ClientHttpRequest request, WebClientStrategies strategies);
+ Mono writeTo(ClientHttpRequest request, ExchangeStrategies strategies);
// Static builder methods
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java
index 8441aec995..476536cc54 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ClientResponse.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -30,7 +30,7 @@ import org.springframework.http.client.reactive.ClientHttpResponse;
import org.springframework.web.reactive.function.BodyExtractor;
/**
- * Represents an HTTP response, as returned by the {@link WebClient}.
+ * Represents an HTTP response, as returned by the {@link ExchangeFunction}.
* Access to headers and body is offered by {@link Headers} and
* {@link #body(BodyExtractor)}, {@link #bodyToMono(Class)}, {@link #bodyToFlux(Class)}
* respectively.
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java
index e0f65d6db8..dadceae1c5 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -154,7 +154,7 @@ class DefaultClientRequestBuilder implements ClientRequest.Builder {
}
@Override
- public Mono writeTo(ClientHttpRequest request, WebClientStrategies strategies) {
+ public Mono writeTo(ClientHttpRequest request, ExchangeStrategies strategies) {
HttpHeaders requestHeaders = request.getHeaders();
if (!this.headers.isEmpty()) {
this.headers.entrySet().stream()
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java
index 25f2c1c38d..44ab32b5c8 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultClientResponse.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -49,10 +49,10 @@ class DefaultClientResponse implements ClientResponse {
private final Headers headers;
- private final WebClientStrategies strategies;
+ private final ExchangeStrategies strategies;
- public DefaultClientResponse(ClientHttpResponse response, WebClientStrategies strategies) {
+ public DefaultClientResponse(ClientHttpResponse response, ExchangeStrategies strategies) {
this.response = response;
this.strategies = strategies;
this.headers = new DefaultHeaders();
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientStrategiesBuilder.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultExchangeStrategiesBuilder.java
similarity index 85%
rename from spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientStrategiesBuilder.java
rename to spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultExchangeStrategiesBuilder.java
index d3f1c2473d..95f7ccf6e7 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientStrategiesBuilder.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultExchangeStrategiesBuilder.java
@@ -46,22 +46,22 @@ import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
- * Default implementation of {@link WebClientStrategies.Builder}.
+ * Default implementation of {@link ExchangeStrategies.Builder}.
*
* @author Arjen Poutsma
* @since 5.0
*/
-class DefaultWebClientStrategiesBuilder implements WebClientStrategies.Builder {
+class DefaultExchangeStrategiesBuilder implements ExchangeStrategies.Builder {
private static final boolean jackson2Present =
ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
- DefaultWebClientStrategiesBuilder.class.getClassLoader()) &&
+ DefaultExchangeStrategiesBuilder.class.getClassLoader()) &&
ClassUtils.isPresent("com.fasterxml.jackson.core.JsonGenerator",
- DefaultWebClientStrategiesBuilder.class.getClassLoader());
+ DefaultExchangeStrategiesBuilder.class.getClassLoader());
private static final boolean jaxb2Present =
ClassUtils.isPresent("javax.xml.bind.Binder",
- DefaultWebClientStrategiesBuilder.class.getClassLoader());
+ DefaultExchangeStrategiesBuilder.class.getClassLoader());
private final List> messageReaders = new ArrayList<>();
@@ -100,43 +100,43 @@ class DefaultWebClientStrategiesBuilder implements WebClientStrategies.Builder {
}
@Override
- public WebClientStrategies.Builder messageReader(HttpMessageReader> messageReader) {
+ public ExchangeStrategies.Builder messageReader(HttpMessageReader> messageReader) {
Assert.notNull(messageReader, "'messageReader' must not be null");
this.messageReaders.add(messageReader);
return this;
}
@Override
- public WebClientStrategies.Builder decoder(Decoder> decoder) {
+ public ExchangeStrategies.Builder decoder(Decoder> decoder) {
Assert.notNull(decoder, "'decoder' must not be null");
return messageReader(new DecoderHttpMessageReader<>(decoder));
}
@Override
- public WebClientStrategies.Builder messageWriter(HttpMessageWriter> messageWriter) {
+ public ExchangeStrategies.Builder messageWriter(HttpMessageWriter> messageWriter) {
Assert.notNull(messageWriter, "'messageWriter' must not be null");
this.messageWriters.add(messageWriter);
return this;
}
@Override
- public WebClientStrategies.Builder encoder(Encoder> encoder) {
+ public ExchangeStrategies.Builder encoder(Encoder> encoder) {
Assert.notNull(encoder, "'encoder' must not be null");
return messageWriter(new EncoderHttpMessageWriter<>(encoder));
}
@Override
- public WebClientStrategies build() {
- return new DefaultWebClientStrategies(this.messageReaders, this.messageWriters);
+ public ExchangeStrategies build() {
+ return new DefaultExchangeStrategies(this.messageReaders, this.messageWriters);
}
- private static class DefaultWebClientStrategies implements WebClientStrategies {
+ private static class DefaultExchangeStrategies implements ExchangeStrategies {
private final List> messageReaders;
private final List> messageWriters;
- public DefaultWebClientStrategies(
+ public DefaultExchangeStrategies(
List> messageReaders,
List> messageWriters) {
this.messageReaders = unmodifiableCopy(messageReaders);
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperations.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java
similarity index 88%
rename from spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperations.java
rename to spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java
index 95d5ffe9a8..248c92eeb0 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperations.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClient.java
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
package org.springframework.web.reactive.function.client;
import java.net.URI;
@@ -38,26 +39,26 @@ import org.springframework.web.util.UriBuilderFactory;
/**
- * Default implementation of {@link WebClientOperations}.
+ * Default implementation of {@link WebClient}.
*
* @author Rossen Stoyanchev
* @since 5.0
*/
-class DefaultWebClientOperations implements WebClientOperations {
+class DefaultWebClient implements WebClient {
- private final WebClient webClient;
+ private final ExchangeFunction exchangeFunction;
private final UriBuilderFactory uriBuilderFactory;
- DefaultWebClientOperations(WebClient webClient, UriBuilderFactory factory) {
- this.webClient = webClient;
+ DefaultWebClient(ExchangeFunction exchangeFunction, UriBuilderFactory factory) {
+ this.exchangeFunction = exchangeFunction;
this.uriBuilderFactory = (factory != null ? factory : new DefaultUriBuilderFactory());
}
- private WebClient getWebClient() {
- return this.webClient;
+ private ExchangeFunction getExchangeFunction() {
+ return this.exchangeFunction;
}
private UriBuilderFactory getUriBuilderFactory() {
@@ -107,9 +108,9 @@ class DefaultWebClientOperations implements WebClientOperations {
@Override
- public WebClientOperations filter(ExchangeFilterFunction filterFunction) {
- WebClient filteredWebClient = this.webClient.filter(filterFunction);
- return new DefaultWebClientOperations(filteredWebClient, this.uriBuilderFactory);
+ public WebClient filter(ExchangeFilterFunction filterFunction) {
+ ExchangeFunction filteredExchangeFunction = this.exchangeFunction.filter(filterFunction);
+ return new DefaultWebClient(filteredExchangeFunction, this.uriBuilderFactory);
}
@@ -219,19 +220,19 @@ class DefaultWebClientOperations implements WebClientOperations {
@Override
public Mono exchange() {
ClientRequest request = this.requestBuilder.headers(this.headers).build();
- return getWebClient().exchange(request);
+ return getExchangeFunction().exchange(request);
}
@Override
public Mono exchange(BodyInserter inserter) {
ClientRequest request = this.requestBuilder.headers(this.headers).body(inserter);
- return getWebClient().exchange(request);
+ return getExchangeFunction().exchange(request);
}
@Override
public > Mono exchange(S publisher, Class elementClass) {
ClientRequest request = this.requestBuilder.headers(this.headers).body(publisher, elementClass);
- return getWebClient().exchange(request);
+ return getExchangeFunction().exchange(request);
}
}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java
index b6100a0bb3..e3ed0817b3 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -16,101 +16,37 @@
package org.springframework.web.reactive.function.client;
-import java.util.logging.Level;
-
-import reactor.core.publisher.Mono;
-
-import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.util.Assert;
+import org.springframework.web.util.UriBuilderFactory;
/**
* Default implementation of {@link WebClient.Builder}.
*
- * @author Arjen Poutsma
+ * @author Rossen Stoyanchev
* @since 5.0
*/
class DefaultWebClientBuilder implements WebClient.Builder {
- private ClientHttpConnector clientHttpConnector;
+ private final ExchangeFunction exchangeFunction;
- private WebClientStrategies strategies = WebClientStrategies.withDefaults();
-
- private ExchangeFilterFunction filter = new NoOpFilter();
+ private UriBuilderFactory uriBuilderFactory;
- public DefaultWebClientBuilder(ClientHttpConnector clientHttpConnector) {
- this.clientHttpConnector = clientHttpConnector;
+ public DefaultWebClientBuilder(ExchangeFunction exchangeFunction) {
+ Assert.notNull(exchangeFunction, "'exchangeFunction' must not be null");
+ this.exchangeFunction = exchangeFunction;
}
- @Override
- public WebClient.Builder strategies(WebClientStrategies strategies) {
- Assert.notNull(strategies, "'strategies' must not be null");
- this.strategies = strategies;
- return this;
- }
@Override
- public WebClient.Builder filter(ExchangeFilterFunction filter) {
- Assert.notNull(filter, "'filter' must not be null");
- this.filter = filter.andThen(this.filter);
+ public WebClient.Builder uriBuilderFactory(UriBuilderFactory uriBuilderFactory) {
+ this.uriBuilderFactory = uriBuilderFactory;
return this;
}
@Override
public WebClient build() {
- return new DefaultWebClient(this.clientHttpConnector, this.strategies, this.filter);
- }
-
- private final static class DefaultWebClient implements WebClient {
-
- private final ClientHttpConnector clientHttpConnector;
-
- private final WebClientStrategies strategies;
-
- private final ExchangeFilterFunction filter;
-
- public DefaultWebClient(
- ClientHttpConnector clientHttpConnector,
- WebClientStrategies strategies,
- ExchangeFilterFunction filter) {
- this.clientHttpConnector = clientHttpConnector;
- this.strategies = strategies;
- this.filter = filter;
- }
-
- @Override
- public Mono exchange(ClientRequest> request) {
- Assert.notNull(request, "'request' must not be null");
-
- return this.filter.filter(request, this::exchangeInternal);
- }
-
- private Mono exchangeInternal(ClientRequest> request) {
- return this.clientHttpConnector
- .connect(request.method(), request.url(),
- clientHttpRequest -> request
- .writeTo(clientHttpRequest, this.strategies))
- .log("org.springframework.web.client.reactive", Level.FINE)
- .map(clientHttpResponse -> new DefaultClientResponse(clientHttpResponse,
- this.strategies));
- }
-
- @Override
- public WebClient filter(ExchangeFilterFunction filter) {
- Assert.notNull(filter, "'filter' must not be null");
-
- ExchangeFilterFunction composedFilter = filter.andThen(this.filter);
-
- return new DefaultWebClient(this.clientHttpConnector, this.strategies, composedFilter);
- }
- }
-
- private class NoOpFilter implements ExchangeFilterFunction {
-
- @Override
- public Mono filter(ClientRequest> request, ExchangeFunction next) {
- return next.exchange(request);
- }
+ return new DefaultWebClient(this.exchangeFunction, this.uriBuilderFactory);
}
}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperationsBuilder.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperationsBuilder.java
deleted file mode 100644
index f8c7749837..0000000000
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/DefaultWebClientOperationsBuilder.java
+++ /dev/null
@@ -1,51 +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
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.web.reactive.function.client;
-
-import org.springframework.util.Assert;
-import org.springframework.web.util.UriBuilderFactory;
-
-/**
- * Default implementation of {@link WebClientOperations.Builder}.
- *
- * @author Rossen Stoyanchev
- * @since 5.0
- */
-class DefaultWebClientOperationsBuilder implements WebClientOperations.Builder {
-
- private final WebClient webClient;
-
- private UriBuilderFactory uriBuilderFactory;
-
-
- public DefaultWebClientOperationsBuilder(WebClient webClient) {
- Assert.notNull(webClient, "WebClient is required");
- this.webClient = webClient;
- }
-
-
- @Override
- public WebClientOperations.Builder uriBuilderFactory(UriBuilderFactory uriBuilderFactory) {
- this.uriBuilderFactory = uriBuilderFactory;
- return this;
- }
-
- @Override
- public WebClientOperations build() {
- return new DefaultWebClientOperations(this.webClient, this.uriBuilderFactory);
- }
-
-}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction.java
index 337dfe824f..7e18483640 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -18,9 +18,21 @@ package org.springframework.web.reactive.function.client;
import reactor.core.publisher.Mono;
+import org.springframework.util.Assert;
+
/**
* Represents a function that exchanges a {@linkplain ClientRequest request} for a (delayed)
- * {@linkplain ClientResponse}.
+ * {@linkplain ClientResponse}. Can be used as an alternative to {@link WebClient}.
+ * For example:
+ *
+ * ExchangeFunction exchangeFunction = ExchangeFunctions.create(new ReactorClientHttpConnector());
+ * ClientRequest<Void> request = ClientRequest.method(HttpMethod.GET,
+ * "http://example.com/resource").build();
+ *
+ * Mono<String> result = exchangeFunction
+ * .exchange(request)
+ * .then(response -> response.bodyToMono(String.class));
+ *
*
* @author Arjen Poutsma
* @since 5.0
@@ -31,8 +43,21 @@ public interface ExchangeFunction {
/**
* Exchange the given request for a response mono.
* @param request the request to exchange
- * @return the response, wrapped in a {@code Mono}
+ * @return the delayed response
*/
Mono exchange(ClientRequest> request);
+ /**
+ * Filters this exchange function with the given {@code ExchangeFilterFunction}, resulting in a
+ * filtered {@code ExchangeFunction}.
+ * @param filter the filter to apply to this exchange
+ * @return the filtered exchange
+ * @see ExchangeFilterFunction#apply(ExchangeFunction)
+ */
+ default ExchangeFunction filter(ExchangeFilterFunction filter) {
+ Assert.notNull(filter, "'filter' must not be null");
+
+ return filter.apply(this);
+ }
+
}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java
new file mode 100644
index 0000000000..f2dd3dcb94
--- /dev/null
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeFunctions.java
@@ -0,0 +1,87 @@
+/*
+ * 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
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.web.reactive.function.client;
+
+import java.util.logging.Level;
+
+import reactor.core.publisher.Mono;
+
+import org.springframework.http.client.reactive.ClientHttpConnector;
+import org.springframework.util.Assert;
+
+/**
+ * Exposes request-response exchange functionality, such as to
+ * {@linkplain #create(ClientHttpConnector) create} an {@code ExchangeFunction} given a
+ * {@code ClientHttpConnector}.
+ *
+ * @author Arjen Poutsma
+ * @since 5.0
+ */
+public abstract class ExchangeFunctions {
+
+ /**
+ * Create a new {@link ExchangeFunction} with the given connector. This method uses
+ * {@linkplain ExchangeStrategies#withDefaults() default strategies}.
+ * @param connector the connector to create connections
+ * @return the created function
+ */
+ public static ExchangeFunction create(ClientHttpConnector connector) {
+ return create(connector, ExchangeStrategies.withDefaults());
+ }
+
+ /**
+ * Create a new {@link ExchangeFunction} with the given connector and strategies.
+ * @param connector the connector to create connections
+ * @param strategies the strategies to use
+ * @return the created function
+ */
+ public static ExchangeFunction create(ClientHttpConnector connector,
+ ExchangeStrategies strategies) {
+ Assert.notNull(connector, "'connector' must not be null");
+ Assert.notNull(strategies, "'strategies' must not be null");
+
+ return new DefaultExchangeFunction(connector, strategies);
+ }
+
+
+ private static class DefaultExchangeFunction implements ExchangeFunction {
+
+ private final ClientHttpConnector connector;
+
+ private final ExchangeStrategies strategies;
+
+ public DefaultExchangeFunction(
+ ClientHttpConnector connector,
+ ExchangeStrategies strategies) {
+ this.connector = connector;
+ this.strategies = strategies;
+ }
+
+ @Override
+ public Mono exchange(ClientRequest> request) {
+ Assert.notNull(request, "'request' must not be null");
+
+ return this.connector
+ .connect(request.method(), request.url(),
+ clientHttpRequest -> request.writeTo(clientHttpRequest, this.strategies))
+ .log("org.springframework.web.reactive.function.client", Level.FINE)
+ .map(clientHttpResponse -> new DefaultClientResponse(clientHttpResponse,
+ this.strategies));
+ }
+ }
+
+}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClientStrategies.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java
similarity index 78%
rename from spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClientStrategies.java
rename to spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java
index 7d40486e87..345e8191a6 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClientStrategies.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/ExchangeStrategies.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -27,17 +27,17 @@ import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.util.Assert;
/**
- * Defines the strategies to be used by the {@link WebClient}. An instance of
+ * Defines the strategies for invoking {@link ExchangeFunction}s. An instance of
* this class is immutable; instances are typically created through the mutable {@link Builder}:
* either through {@link #builder()} to set up default strategies, or {@link #empty()} to start from
- * scratch. Alternatively, {@code WebClientStrategies} instances can be created through
+ * scratch. Alternatively, {@code ExchangeStrategies} instances can be created through
* {@link #of(Supplier, Supplier)}.
*
* @author Brian Clozel
* @author Arjen Poutsma
* @since 5.0
*/
-public interface WebClientStrategies {
+public interface ExchangeStrategies {
// Instance methods
@@ -59,38 +59,38 @@ public interface WebClientStrategies {
// Static methods
/**
- * Return a new {@code WebClientStrategies} with default initialization.
- * @return the new {@code WebClientStrategies}
+ * Return a new {@code ExchangeStrategies} with default initialization.
+ * @return the new {@code ExchangeStrategies}
*/
- static WebClientStrategies withDefaults() {
+ static ExchangeStrategies withDefaults() {
return builder().build();
}
/**
- * Return a new {@code WebClientStrategies} based on the given
+ * Return a new {@code ExchangeStrategies} based on the given
* {@linkplain ApplicationContext application context}.
* The returned supplier will search for all {@link HttpMessageReader}, and
* {@link HttpMessageWriter} instances in the given application context and return them for
* {@link #messageReaders()}, and {@link #messageWriters()} respectively.
* @param applicationContext the application context to base the strategies on
- * @return the new {@code WebClientStrategies}
+ * @return the new {@code ExchangeStrategies}
*/
- static WebClientStrategies of(ApplicationContext applicationContext) {
+ static ExchangeStrategies of(ApplicationContext applicationContext) {
return builder(applicationContext).build();
}
/**
- * Return a new {@code WebClientStrategies} described by the given supplier functions.
+ * Return a new {@code ExchangeStrategies} described by the given supplier functions.
* All provided supplier function parameters can be {@code null} to indicate an empty
* stream is to be returned.
* @param messageReaders the supplier function for {@link HttpMessageReader} instances (can be {@code null})
* @param messageWriters the supplier function for {@link HttpMessageWriter} instances (can be {@code null})
- * @return the new {@code WebClientStrategies}
+ * @return the new {@code ExchangeStrategies}
*/
- static WebClientStrategies of(Supplier>> messageReaders,
+ static ExchangeStrategies of(Supplier>> messageReaders,
Supplier>> messageWriters) {
- return new WebClientStrategies() {
+ return new ExchangeStrategies() {
@Override
public Supplier>> messageReaders() {
return checkForNull(messageReaders);
@@ -109,11 +109,11 @@ public interface WebClientStrategies {
// Builder methods
/**
- * Return a mutable builder for a {@code WebClientStrategies} with default initialization.
+ * Return a mutable builder for a {@code ExchangeStrategies} with default initialization.
* @return the builder
*/
static Builder builder() {
- DefaultWebClientStrategiesBuilder builder = new DefaultWebClientStrategiesBuilder();
+ DefaultExchangeStrategiesBuilder builder = new DefaultExchangeStrategiesBuilder();
builder.defaultConfiguration();
return builder;
}
@@ -128,22 +128,22 @@ public interface WebClientStrategies {
*/
static Builder builder(ApplicationContext applicationContext) {
Assert.notNull(applicationContext, "ApplicationContext must not be null");
- DefaultWebClientStrategiesBuilder builder = new DefaultWebClientStrategiesBuilder();
+ DefaultExchangeStrategiesBuilder builder = new DefaultExchangeStrategiesBuilder();
builder.applicationContext(applicationContext);
return builder;
}
/**
- * Return a mutable, empty builder for a {@code WebClientStrategies}.
+ * Return a mutable, empty builder for a {@code ExchangeStrategies}.
* @return the builder
*/
static Builder empty() {
- return new DefaultWebClientStrategiesBuilder();
+ return new DefaultExchangeStrategiesBuilder();
}
/**
- * A mutable builder for a {@link WebClientStrategies}.
+ * A mutable builder for a {@link ExchangeStrategies}.
*/
interface Builder {
@@ -180,10 +180,10 @@ public interface WebClientStrategies {
Builder encoder(Encoder> encoder);
/**
- * Builds the {@link WebClientStrategies}.
+ * Builds the {@link ExchangeStrategies}.
* @return the built strategies
*/
- WebClientStrategies build();
+ ExchangeStrategies build();
}
}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClient.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClient.java
index 8ecd734f40..b78c66b734 100644
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClient.java
+++ b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClient.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -16,43 +16,97 @@
package org.springframework.web.reactive.function.client;
+import java.net.URI;
+import java.nio.charset.Charset;
+import java.time.ZonedDateTime;
+import java.util.function.Function;
+
+import org.reactivestreams.Publisher;
import reactor.core.publisher.Mono;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ClientHttpConnector;
-import org.springframework.util.Assert;
+import org.springframework.http.client.reactive.ClientHttpRequest;
+import org.springframework.util.MultiValueMap;
+import org.springframework.web.reactive.function.BodyInserter;
+import org.springframework.web.util.UriBuilderFactory;
/**
- * Reactive Web client supporting the HTTP/1.1 protocol. Main entry point is through the
- * {@link #exchange(ClientRequest)} method.
+ * The main class for performing Web requests.
*
- * For example:
*
- * WebClient client = WebClient.create(new ReactorClientHttpConnector());
- * ClientRequest<Void> request = ClientRequest.GET("http://example.com/resource").build();
*
- * Mono<String> result = client
- * .exchange(request)
- * .then(response -> response.bodyToMono(String.class));
+ * // Create ExchangeFunction (application-wide)
+ *
+ * ClientHttpConnector connector = new ReactorClientHttpConnector();
+ * ExchangeFunction exchangeFunction = ExchangeFunctions.create(connector);
+ *
+ * // Create WebClient (per base URI)
+ *
+ * String baseUri = "http://abc.com";
+ * UriBuilderFactory factory = new DefaultUriBuilderFactory(baseUri);
+ * WebClient operations = WebClient.create(exchangeFunction, factory);
+ *
+ * // Perform requests...
+ *
+ * Mono result = operations.get()
+ * .uri("/foo")
+ * .exchange()
+ * .then(response -> response.bodyToMono(String.class));
*
*
- * @author Brian Clozel
+ * @author Rossen Stoyanchev
* @author Arjen Poutsma
* @since 5.0
*/
-public interface WebClient extends ExchangeFunction {
+public interface WebClient {
/**
- * Exchange the given request for a response mono. Invoking this method performs the actual
- * HTTP request/response exchange.
- * @param request the request to exchange
- * @return the response, wrapped in a {@code Mono}
+ * Prepare an HTTP GET request.
+ * @return a spec for specifying the target URL
*/
- @Override
- Mono exchange(ClientRequest> request);
+ UriSpec get();
/**
- * Filters this client with the given {@code ExchangeFilterFunction}, resulting in a filtered
- * {@code WebClient}.
+ * Prepare an HTTP HEAD request.
+ * @return a spec for specifying the target URL
+ */
+ UriSpec head();
+
+ /**
+ * Prepare an HTTP POST request.
+ * @return a spec for specifying the target URL
+ */
+ UriSpec post();
+
+ /**
+ * Prepare an HTTP PUT request.
+ * @return a spec for specifying the target URL
+ */
+ UriSpec put();
+
+ /**
+ * Prepare an HTTP PATCH request.
+ * @return a spec for specifying the target URL
+ */
+ UriSpec patch();
+
+ /**
+ * Prepare an HTTP DELETE request.
+ * @return a spec for specifying the target URL
+ */
+ UriSpec delete();
+
+ /**
+ * Prepare an HTTP OPTIONS request.
+ * @return a spec for specifying the target URL
+ */
+ UriSpec options();
+
+
+ /**
+ * Filter the client with the given {@code ExchangeFilterFunction}.
* @param filterFunction the filter to apply to this client
* @return the filtered client
* @see ExchangeFilterFunction#apply(ExchangeFunction)
@@ -60,52 +114,204 @@ public interface WebClient extends ExchangeFunction {
WebClient filter(ExchangeFilterFunction filterFunction);
+ // Static, factory methods
+
/**
- * Create a new instance of {@code WebClient} with the given connector. This method uses
- * {@linkplain WebClientStrategies#withDefaults() default strategies}.
- * @param connector the connector to create connections
- * @return the created client
+ * Create {@code WebClient} that uses the given {@link ClientHttpConnector}.
+ * @param connector the underlying connector to use
*/
static WebClient create(ClientHttpConnector connector) {
- return builder(connector).build();
+ return create(ExchangeFunctions.create(connector));
+
}
/**
- * Return a builder for a {@code WebClient}.
- * @param connector the connector to create connections
- * @return a web client builder
+ * Create {@code WebClient} that uses the given {@link ClientHttpConnector} and
+ * {@link ExchangeStrategies}.
+ * @param connector the underlying connector to use
+ * @param strategies the strategies to use
*/
- static Builder builder(ClientHttpConnector connector) {
- Assert.notNull(connector, "'connector' must not be null");
- return new DefaultWebClientBuilder(connector);
+ static WebClient create(ClientHttpConnector connector, ExchangeStrategies strategies) {
+ return create(ExchangeFunctions.create(connector, strategies));
}
+ /**
+ * Create {@code WebClient} that wraps the given {@link ExchangeFunction}.
+ * @param exchangeFunction the underlying exchange function to use
+ */
+ static WebClient create(ExchangeFunction exchangeFunction) {
+ return builder(exchangeFunction).build();
+ }
+
+ /**
+ * Create {@code WebClient} with a builder for additional
+ * configuration options.
+ * @param exchangeFunction the underlying exchange function to use
+ */
+ static WebClient.Builder builder(ExchangeFunction exchangeFunction) {
+ return new DefaultWebClientBuilder(exchangeFunction);
+ }
+
+
/**
* A mutable builder for a {@link WebClient}.
*/
interface Builder {
/**
- * Replaces the default strategies with the ones provided by the given
- * {@code WebClientStrategies}.
- * @param strategies the strategies to use
- * @return this builder
+ * Configure a {@code UriBuilderFactory} for use with this client for
+ * example to define a common "base" URI.
+ * @param uriBuilderFactory the URI builder factory
*/
- Builder strategies(WebClientStrategies strategies);
+ Builder uriBuilderFactory(UriBuilderFactory uriBuilderFactory);
/**
- * Adds a filter function before the currently registered filters (if any).
- * @param filter the filter to add
- * @return this builder
- */
- Builder filter(ExchangeFilterFunction filter);
-
- /**
- * Builds the {@code WebClient}.
- * @return the built client
+ * Builder the {@link WebClient} instance.
*/
WebClient build();
+
}
+ /**
+ * Contract for specifying the URI for a request.
+ */
+ interface UriSpec {
+
+ /**
+ * Specify the URI using an absolute, fully constructed {@link URI}.
+ */
+ HeaderSpec uri(URI uri);
+
+ /**
+ * Specify the URI for the request using a URI template and URI variables.
+ * If a {@link UriBuilderFactory} was configured for the client (e.g.
+ * with a base URI) it will be used to expand the URI template.
+ * @see Builder#uriBuilderFactory(UriBuilderFactory)
+ */
+ HeaderSpec uri(String uri, Object... uriVariables);
+
+ /**
+ * Build the URI for the request using the {@link UriBuilderFactory}
+ * configured for this client.
+ * @see Builder#uriBuilderFactory(UriBuilderFactory)
+ */
+ HeaderSpec uri(Function uriFunction);
+
+ }
+
+ /**
+ * Contract for specifying request headers leading up to the exchange.
+ */
+ interface HeaderSpec {
+
+ /**
+ * Set the list of acceptable {@linkplain MediaType media types}, as
+ * specified by the {@code Accept} header.
+ * @param acceptableMediaTypes the acceptable media types
+ * @return this builder
+ */
+ HeaderSpec accept(MediaType... acceptableMediaTypes);
+
+ /**
+ * Set the list of acceptable {@linkplain Charset charsets}, as specified
+ * by the {@code Accept-Charset} header.
+ * @param acceptableCharsets the acceptable charsets
+ * @return this builder
+ */
+ HeaderSpec acceptCharset(Charset... acceptableCharsets);
+
+ /**
+ * Set the length of the body in bytes, as specified by the
+ * {@code Content-Length} header.
+ * @param contentLength the content length
+ * @return this builder
+ * @see HttpHeaders#setContentLength(long)
+ */
+ HeaderSpec contentLength(long contentLength);
+
+ /**
+ * Set the {@linkplain MediaType media type} of the body, as specified
+ * by the {@code Content-Type} header.
+ * @param contentType the content type
+ * @return this builder
+ * @see HttpHeaders#setContentType(MediaType)
+ */
+ HeaderSpec contentType(MediaType contentType);
+
+ /**
+ * Add a cookie with the given name and value.
+ * @param name the cookie name
+ * @param value the cookie value
+ * @return this builder
+ */
+ HeaderSpec cookie(String name, String value);
+
+ /**
+ * Copy the given cookies into the entity's cookies map.
+ *
+ * @param cookies the existing cookies to copy from
+ * @return this builder
+ */
+ HeaderSpec cookies(MultiValueMap cookies);
+
+ /**
+ * Set the value of the {@code If-Modified-Since} header.
+ * The date should be specified as the number of milliseconds since
+ * January 1, 1970 GMT.
+ * @param ifModifiedSince the new value of the header
+ * @return this builder
+ */
+ HeaderSpec ifModifiedSince(ZonedDateTime ifModifiedSince);
+
+ /**
+ * Set the values of the {@code If-None-Match} header.
+ * @param ifNoneMatches the new value of the header
+ * @return this builder
+ */
+ HeaderSpec ifNoneMatch(String... ifNoneMatches);
+
+ /**
+ * Add the given, single header value under the given name.
+ * @param headerName the header name
+ * @param headerValues the header value(s)
+ * @return this builder
+ */
+ HeaderSpec header(String headerName, String... headerValues);
+
+ /**
+ * Copy the given headers into the entity's headers map.
+ * @param headers the existing headers to copy from
+ * @return this builder
+ */
+ HeaderSpec headers(HttpHeaders headers);
+
+ /**
+ * Perform the request without a request body.
+ * @return a {@code Mono} with the response
+ */
+ Mono exchange();
+
+ /**
+ * Set the body of the request to the given {@code BodyInserter} and
+ * perform the request.
+ * @param inserter the {@code BodyInserter} that writes to the request
+ * @param the type contained in the body
+ * @return a {@code Mono} with the response
+ */
+ Mono exchange(BodyInserter inserter);
+
+ /**
+ * Set the body of the request to the given {@code Publisher} and
+ * perform the request.
+ * @param publisher the {@code Publisher} to write to the request
+ * @param elementClass the class of elements contained in the publisher
+ * @param the type of the elements contained in the publisher
+ * @param the type of the {@code Publisher}
+ * @return a {@code Mono} with the response
+ */
+ > Mono exchange(S publisher, Class elementClass);
+
+ }
+
}
diff --git a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClientOperations.java b/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClientOperations.java
deleted file mode 100644
index 7200f8fb8c..0000000000
--- a/spring-web-reactive/src/main/java/org/springframework/web/reactive/function/client/WebClientOperations.java
+++ /dev/null
@@ -1,295 +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
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.web.reactive.function.client;
-
-import java.net.URI;
-import java.nio.charset.Charset;
-import java.time.ZonedDateTime;
-import java.util.function.Function;
-
-import org.reactivestreams.Publisher;
-import reactor.core.publisher.Mono;
-
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.http.client.reactive.ClientHttpRequest;
-import org.springframework.util.MultiValueMap;
-import org.springframework.web.reactive.function.BodyInserter;
-import org.springframework.web.util.UriBuilderFactory;
-
-/**
- * The main class for performing requests through a WebClient.
- *
- *
- *
- * // Create WebClient (application-wide)
- *
- * ClientHttpConnector connector = new ReactorClientHttpConnector();
- * WebClient webClient = WebClient.create(connector);
- *
- * // Create WebClientOperations (per base URI)
- *
- * String baseUri = "http://abc.com";
- * UriBuilderFactory factory = new DefaultUriBuilderFactory(baseUri);
- * WebClientOperations operations = WebClientOperations.create(webClient, factory);
- *
- * // Perform requests...
- *
- * Mono result = operations.get()
- * .uri("/foo")
- * .exchange()
- * .then(response -> response.bodyToMono(String.class));
- *
- *
- * @author Rossen Stoyanchev
- * @since 5.0
- */
-public interface WebClientOperations {
-
- /**
- * Prepare an HTTP GET request.
- * @return a spec for specifying the target URL
- */
- UriSpec get();
-
- /**
- * Prepare an HTTP HEAD request.
- * @return a spec for specifying the target URL
- */
- UriSpec head();
-
- /**
- * Prepare an HTTP POST request.
- * @return a spec for specifying the target URL
- */
- UriSpec post();
-
- /**
- * Prepare an HTTP PUT request.
- * @return a spec for specifying the target URL
- */
- UriSpec put();
-
- /**
- * Prepare an HTTP PATCH request.
- * @return a spec for specifying the target URL
- */
- UriSpec patch();
-
- /**
- * Prepare an HTTP DELETE request.
- * @return a spec for specifying the target URL
- */
- UriSpec delete();
-
- /**
- * Prepare an HTTP OPTIONS request.
- * @return a spec for specifying the target URL
- */
- UriSpec options();
-
-
- /**
- * Filter the client with the given {@code ExchangeFilterFunction}.
- * @param filterFunction the filter to apply to this client
- * @return the filtered client
- * @see ExchangeFilterFunction#apply(ExchangeFunction)
- */
- WebClientOperations filter(ExchangeFilterFunction filterFunction);
-
-
- // Static, factory methods
-
- /**
- * Create {@link WebClientOperations} that wraps the given {@link WebClient}.
- * @param webClient the underlying client to use
- */
- static WebClientOperations create(WebClient webClient) {
- return builder(webClient).build();
- }
-
- /**
- * Create {@link WebClientOperations} with a builder for additional
- * configuration options.
- * @param webClient the underlying client to use
- */
- static WebClientOperations.Builder builder(WebClient webClient) {
- return new DefaultWebClientOperationsBuilder(webClient);
- }
-
-
- /**
- * A mutable builder for a {@link WebClientOperations}.
- */
- interface Builder {
-
- /**
- * Configure a {@code UriBuilderFactory} for use with this client for
- * example to define a common "base" URI.
- * @param uriBuilderFactory the URI builder factory
- */
- Builder uriBuilderFactory(UriBuilderFactory uriBuilderFactory);
-
- /**
- * Builder the {@link WebClient} instance.
- */
- WebClientOperations build();
-
- }
-
-
- /**
- * Contract for specifying the URI for a request.
- */
- interface UriSpec {
-
- /**
- * Specify the URI using an absolute, fully constructed {@link URI}.
- */
- HeaderSpec uri(URI uri);
-
- /**
- * Specify the URI for the request using a URI template and URI variables.
- * If a {@link UriBuilderFactory} was configured for the client (e.g.
- * with a base URI) it will be used to expand the URI template.
- * @see Builder#uriBuilderFactory(UriBuilderFactory)
- */
- HeaderSpec uri(String uri, Object... uriVariables);
-
- /**
- * Build the URI for the request using the {@link UriBuilderFactory}
- * configured for this client.
- * @see Builder#uriBuilderFactory(UriBuilderFactory)
- */
- HeaderSpec uri(Function uriFunction);
-
- }
-
- /**
- * Contract for specifying request headers leading up to the exchange.
- */
- interface HeaderSpec {
-
- /**
- * Set the list of acceptable {@linkplain MediaType media types}, as
- * specified by the {@code Accept} header.
- * @param acceptableMediaTypes the acceptable media types
- * @return this builder
- */
- HeaderSpec accept(MediaType... acceptableMediaTypes);
-
- /**
- * Set the list of acceptable {@linkplain Charset charsets}, as specified
- * by the {@code Accept-Charset} header.
- * @param acceptableCharsets the acceptable charsets
- * @return this builder
- */
- HeaderSpec acceptCharset(Charset... acceptableCharsets);
-
- /**
- * Set the length of the body in bytes, as specified by the
- * {@code Content-Length} header.
- * @param contentLength the content length
- * @return this builder
- * @see HttpHeaders#setContentLength(long)
- */
- HeaderSpec contentLength(long contentLength);
-
- /**
- * Set the {@linkplain MediaType media type} of the body, as specified
- * by the {@code Content-Type} header.
- * @param contentType the content type
- * @return this builder
- * @see HttpHeaders#setContentType(MediaType)
- */
- HeaderSpec contentType(MediaType contentType);
-
- /**
- * Add a cookie with the given name and value.
- * @param name the cookie name
- * @param value the cookie value
- * @return this builder
- */
- HeaderSpec cookie(String name, String value);
-
- /**
- * Copy the given cookies into the entity's cookies map.
- *
- * @param cookies the existing cookies to copy from
- * @return this builder
- */
- HeaderSpec cookies(MultiValueMap cookies);
-
- /**
- * Set the value of the {@code If-Modified-Since} header.
- * The date should be specified as the number of milliseconds since
- * January 1, 1970 GMT.
- * @param ifModifiedSince the new value of the header
- * @return this builder
- */
- HeaderSpec ifModifiedSince(ZonedDateTime ifModifiedSince);
-
- /**
- * Set the values of the {@code If-None-Match} header.
- * @param ifNoneMatches the new value of the header
- * @return this builder
- */
- HeaderSpec ifNoneMatch(String... ifNoneMatches);
-
- /**
- * Add the given, single header value under the given name.
- * @param headerName the header name
- * @param headerValues the header value(s)
- * @return this builder
- */
- HeaderSpec header(String headerName, String... headerValues);
-
- /**
- * Copy the given headers into the entity's headers map.
- * @param headers the existing headers to copy from
- * @return this builder
- */
- HeaderSpec headers(HttpHeaders headers);
-
- /**
- * Perform the request without a request body.
- * @return a {@code Mono} with the response
- */
- Mono exchange();
-
- /**
- * Set the body of the request to the given {@code BodyInserter} and
- * perform the request.
- * @param inserter the {@code BodyInserter} that writes to the request
- * @param the type contained in the body
- * @return a {@code Mono} with the response
- */
- Mono exchange(BodyInserter inserter);
-
- /**
- * Set the body of the request to the given {@code Publisher} and
- * perform the request.
- * @param publisher the {@code Publisher} to write to the request
- * @param elementClass the class of elements contained in the publisher
- * @param the type of the elements contained in the publisher
- * @param the type of the {@code Publisher}
- * @return a {@code Mono} with the response
- */
- > Mono exchange(S publisher, Class elementClass);
-
- }
-
-}
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java
index 18810cfd57..aca5c1614b 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/FlushingIntegrationTests.java
@@ -36,19 +36,20 @@ import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.bootstrap.RxNettyHttpServer;
import org.springframework.web.reactive.function.BodyExtractors;
+import org.springframework.web.reactive.function.client.ExchangeFunction;
+import org.springframework.web.reactive.function.client.ExchangeFunctions;
import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClientOperations;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilderFactory;
-import static org.junit.Assert.*;
+import static org.junit.Assert.assertTrue;
/**
* @author Sebastien Deleuze
*/
public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTests {
- private WebClientOperations operations;
+ private WebClient webClient;
@Before
@@ -58,15 +59,15 @@ public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTest
super.setup();
- WebClient client = WebClient.create(new ReactorClientHttpConnector());
+ ExchangeFunction exchange = ExchangeFunctions.create(new ReactorClientHttpConnector());
UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port);
- this.operations = WebClientOperations.builder(client).uriBuilderFactory(factory).build();
+ this.webClient = WebClient.builder(exchange).uriBuilderFactory(factory).build();
}
@Test
public void writeAndFlushWith() throws Exception {
- Mono result = this.operations.get()
+ Mono result = this.webClient.get()
.uri("/write-and-flush")
.exchange()
.flatMap(response -> response.body(BodyExtractors.toFlux(String.class)))
@@ -81,7 +82,7 @@ public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTest
@Test // SPR-14991
public void writeAndAutoFlushOnComplete() {
- Mono result = this.operations.get()
+ Mono result = this.webClient.get()
.uri("/write-and-complete")
.exchange()
.flatMap(response -> response.bodyToFlux(String.class))
@@ -95,7 +96,7 @@ public class FlushingIntegrationTests extends AbstractHttpHandlerIntegrationTest
@Test // SPR-14992
public void writeAndAutoFlushBeforeComplete() {
- Flux result = this.operations.get()
+ Flux result = this.webClient.get()
.uri("/write-and-never-complete")
.exchange()
.flatMap(response -> response.bodyToFlux(String.class));
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java
index b16ad3c0c7..749210bf09 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientRequestBuilderTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -83,7 +83,7 @@ public class DefaultClientRequestBuilderTests {
.build();
MockClientHttpRequest request = new MockClientHttpRequest(GET, "/");
- WebClientStrategies strategies = mock(WebClientStrategies.class);
+ ExchangeStrategies strategies = mock(ExchangeStrategies.class);
result.writeTo(request, strategies).block();
@@ -110,7 +110,7 @@ public class DefaultClientRequestBuilderTests {
List> messageWriters = new ArrayList<>();
messageWriters.add(new EncoderHttpMessageWriter<>(new CharSequenceEncoder()));
- WebClientStrategies strategies = mock(WebClientStrategies.class);
+ ExchangeStrategies strategies = mock(ExchangeStrategies.class);
when(strategies.messageWriters()).thenReturn(messageWriters::stream);
MockClientHttpRequest request = new MockClientHttpRequest(GET, "/");
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java
index 49ef89f9d8..aee80b6283 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/DefaultClientResponseTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -55,7 +55,7 @@ public class DefaultClientResponseTests {
private ClientHttpResponse mockResponse;
- private WebClientStrategies mockWebClientStrategies;
+ private ExchangeStrategies mockExchangeStrategies;
private DefaultClientResponse defaultClientResponse;
@@ -63,9 +63,9 @@ public class DefaultClientResponseTests {
@Before
public void createMocks() {
mockResponse = mock(ClientHttpResponse.class);
- mockWebClientStrategies = mock(WebClientStrategies.class);
+ mockExchangeStrategies = mock(ExchangeStrategies.class);
- defaultClientResponse = new DefaultClientResponse(mockResponse, mockWebClientStrategies);
+ defaultClientResponse = new DefaultClientResponse(mockResponse, mockExchangeStrategies);
}
@Test
@@ -110,7 +110,7 @@ public class DefaultClientResponseTests {
Set> messageReaders = Collections
.singleton(new DecoderHttpMessageReader(new StringDecoder()));
- when(mockWebClientStrategies.messageReaders()).thenReturn(messageReaders::stream);
+ when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream);
Mono resultMono = defaultClientResponse.body(toMono(String.class));
assertEquals("foo", resultMono.block());
@@ -131,7 +131,7 @@ public class DefaultClientResponseTests {
Set> messageReaders = Collections
.singleton(new DecoderHttpMessageReader(new StringDecoder()));
- when(mockWebClientStrategies.messageReaders()).thenReturn(messageReaders::stream);
+ when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream);
Mono resultMono = defaultClientResponse.bodyToMono(String.class);
assertEquals("foo", resultMono.block());
@@ -146,7 +146,7 @@ public class DefaultClientResponseTests {
Set> messageReaders = Collections
.singleton(new DecoderHttpMessageReader(new StringDecoder()));
- when(mockWebClientStrategies.messageReaders()).thenReturn(messageReaders::stream);
+ when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream);
Mono resultMono = defaultClientResponse.bodyToMono(String.class);
@@ -170,7 +170,7 @@ public class DefaultClientResponseTests {
Set> messageReaders = Collections
.singleton(new DecoderHttpMessageReader(new StringDecoder()));
- when(mockWebClientStrategies.messageReaders()).thenReturn(messageReaders::stream);
+ when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream);
Flux resultFlux = defaultClientResponse.bodyToFlux(String.class);
Mono> result = resultFlux.collectList();
@@ -186,7 +186,7 @@ public class DefaultClientResponseTests {
Set> messageReaders = Collections
.singleton(new DecoderHttpMessageReader(new StringDecoder()));
- when(mockWebClientStrategies.messageReaders()).thenReturn(messageReaders::stream);
+ when(mockExchangeStrategies.messageReaders()).thenReturn(messageReaders::stream);
Flux resultFlux = defaultClientResponse.bodyToFlux(String.class);
StepVerifier.create(resultFlux)
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientStrategiesTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/ExchangeStrategiesTests.java
similarity index 92%
rename from spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientStrategiesTests.java
rename to spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/ExchangeStrategiesTests.java
index e5a13bbca0..b9ea5a3d4c 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientStrategiesTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/ExchangeStrategiesTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -42,11 +42,11 @@ import static org.junit.Assert.assertTrue;
/**
* @author Arjen Poutsma
*/
-public class WebClientStrategiesTests {
+public class ExchangeStrategiesTests {
@Test
public void empty() {
- WebClientStrategies strategies = WebClientStrategies.empty().build();
+ ExchangeStrategies strategies = ExchangeStrategies.empty().build();
assertEquals(Optional.empty(), strategies.messageReaders().get().findFirst());
assertEquals(Optional.empty(), strategies.messageWriters().get().findFirst());
}
@@ -56,7 +56,7 @@ public class WebClientStrategiesTests {
HttpMessageReader> messageReader = new DummyMessageReader();
HttpMessageWriter> messageWriter = new DummyMessageWriter();
- WebClientStrategies strategies = WebClientStrategies.of(
+ ExchangeStrategies strategies = ExchangeStrategies.of(
() -> Stream.of(messageReader),
() -> Stream.of(messageWriter));
@@ -74,7 +74,7 @@ public class WebClientStrategiesTests {
applicationContext.registerSingleton("messageReader", DummyMessageReader.class);
applicationContext.refresh();
- WebClientStrategies strategies = WebClientStrategies.of(applicationContext);
+ ExchangeStrategies strategies = ExchangeStrategies.of(applicationContext);
assertTrue(strategies.messageReaders().get()
.allMatch(r -> r instanceof DummyMessageReader));
assertTrue(strategies.messageWriters().get()
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java
index 5dabfc061c..209cf4c93c 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -43,7 +43,7 @@ import static org.junit.Assert.assertThat;
import static org.springframework.web.reactive.function.BodyInserters.fromObject;
/**
- * Integration tests using a {@link WebClient} through {@link WebClientOperations}.
+ * Integration tests using a {@link ExchangeFunction} through {@link WebClient}.
*
* @author Brian Clozel
* @author Rossen Stoyanchev
@@ -52,17 +52,17 @@ public class WebClientIntegrationTests {
private MockWebServer server;
- private WebClientOperations operations;
+ private WebClient webClient;
@Before
public void setup() {
this.server = new MockWebServer();
- WebClient webClient = WebClient.create(new ReactorClientHttpConnector());
+ ExchangeFunction exchangeFunction = ExchangeFunctions.create(new ReactorClientHttpConnector());
UriBuilderFactory uriBuilderFactory = new DefaultUriBuilderFactory(this.server.url("/").toString());
- this.operations = WebClientOperations.builder(webClient)
+ this.webClient = WebClient.builder(exchangeFunction)
.uriBuilderFactory(uriBuilderFactory)
.build();
}
@@ -77,7 +77,7 @@ public class WebClientIntegrationTests {
public void headers() throws Exception {
this.server.enqueue(new MockResponse().setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
- Mono result = this.operations.get()
+ Mono result = this.webClient.get()
.uri("/greeting?name=Spring")
.exchange()
.map(response -> response.headers().asHttpHeaders());
@@ -101,7 +101,7 @@ public class WebClientIntegrationTests {
public void plainText() throws Exception {
this.server.enqueue(new MockResponse().setBody("Hello Spring!"));
- Mono result = this.operations.get()
+ Mono result = this.webClient.get()
.uri("/greeting?name=Spring")
.header("X-Test-Header", "testvalue")
.exchange()
@@ -125,7 +125,7 @@ public class WebClientIntegrationTests {
this.server.enqueue(new MockResponse().setHeader("Content-Type", "application/json")
.setBody(content));
- Mono result = this.operations.get()
+ Mono result = this.webClient.get()
.uri("/json")
.accept(MediaType.APPLICATION_JSON)
.exchange()
@@ -147,7 +147,7 @@ public class WebClientIntegrationTests {
this.server.enqueue(new MockResponse().setHeader("Content-Type", "application/json")
.setBody("{\"bar\":\"barbar\",\"foo\":\"foofoo\"}"));
- Mono result = this.operations.get()
+ Mono result = this.webClient.get()
.uri("/pojo")
.accept(MediaType.APPLICATION_JSON)
.exchange()
@@ -169,7 +169,7 @@ public class WebClientIntegrationTests {
this.server.enqueue(new MockResponse().setHeader("Content-Type", "application/json")
.setBody("[{\"bar\":\"bar1\",\"foo\":\"foo1\"},{\"bar\":\"bar2\",\"foo\":\"foo2\"}]"));
- Flux result = this.operations.get()
+ Flux result = this.webClient.get()
.uri("/pojos")
.accept(MediaType.APPLICATION_JSON)
.exchange()
@@ -193,7 +193,7 @@ public class WebClientIntegrationTests {
.setHeader("Content-Type", "application/json")
.setBody("{\"bar\":\"BARBAR\",\"foo\":\"FOOFOO\"}"));
- Mono result = this.operations.post()
+ Mono result = this.webClient.post()
.uri("/pojo/capitalize")
.accept(MediaType.APPLICATION_JSON)
.contentType(MediaType.APPLICATION_JSON)
@@ -219,7 +219,7 @@ public class WebClientIntegrationTests {
this.server.enqueue(new MockResponse()
.setHeader("Content-Type", "text/plain").setBody("test"));
- Mono result = this.operations.get()
+ Mono result = this.webClient.get()
.uri("/test")
.cookie("testkey", "testvalue")
.exchange()
@@ -241,7 +241,7 @@ public class WebClientIntegrationTests {
this.server.enqueue(new MockResponse().setResponseCode(404)
.setHeader("Content-Type", "text/plain").setBody("Not Found"));
- Mono result = this.operations.get().uri("/greeting?name=Spring").exchange();
+ Mono result = this.webClient.get().uri("/greeting?name=Spring").exchange();
StepVerifier.create(result)
.consumeNextWith(response -> assertEquals(HttpStatus.NOT_FOUND, response.statusCode()))
@@ -258,7 +258,7 @@ public class WebClientIntegrationTests {
public void buildFilter() throws Exception {
this.server.enqueue(new MockResponse().setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
- WebClientOperations filteredClient = this.operations.filter(
+ WebClient filteredClient = this.webClient.filter(
(request, next) -> {
ClientRequest> filteredRequest = ClientRequest.from(request).header("foo", "bar").build();
return next.exchange(filteredRequest);
@@ -284,7 +284,7 @@ public class WebClientIntegrationTests {
public void filter() throws Exception {
this.server.enqueue(new MockResponse().setHeader("Content-Type", "text/plain").setBody("Hello Spring!"));
- WebClientOperations filteredClient = this.operations.filter(
+ WebClient filteredClient = this.webClient.filter(
(request, next) -> {
ClientRequest> filteredRequest = ClientRequest.from(request).header("foo", "bar").build();
return next.exchange(filteredRequest);
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java
index e58fc19431..a4d923bbd7 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/function/server/SseHandlerFunctionIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -26,8 +26,9 @@ import reactor.test.StepVerifier;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.http.codec.ServerSentEvent;
+import org.springframework.web.reactive.function.client.ExchangeFunction;
+import org.springframework.web.reactive.function.client.ExchangeFunctions;
import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClientOperations;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilderFactory;
@@ -44,15 +45,16 @@ import static org.springframework.web.reactive.function.server.RouterFunctions.r
*/
public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIntegrationTests {
- private WebClientOperations operations;
+ private WebClient webClient;
@Before
public void setup() throws Exception {
super.setup();
- WebClient client = WebClient.create(new ReactorClientHttpConnector());
+ ExchangeFunction exchangeFunction =
+ ExchangeFunctions.create(new ReactorClientHttpConnector());
UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port);
- this.operations = WebClientOperations.builder(client).uriBuilderFactory(factory).build();
+ this.webClient = WebClient.builder(exchangeFunction).uriBuilderFactory(factory).build();
}
@Override
@@ -65,7 +67,7 @@ public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIn
@Test
public void sseAsString() throws Exception {
- Flux result = this.operations.get()
+ Flux result = this.webClient.get()
.uri("/string")
.accept(TEXT_EVENT_STREAM)
.exchange()
@@ -79,7 +81,7 @@ public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIn
}
@Test
public void sseAsPerson() throws Exception {
- Flux result = this.operations.get()
+ Flux result = this.webClient.get()
.uri("/person")
.accept(TEXT_EVENT_STREAM)
.exchange()
@@ -94,7 +96,7 @@ public class SseHandlerFunctionIntegrationTests extends AbstractRouterFunctionIn
@Test
public void sseAsEvent() throws Exception {
- Flux> result = this.operations.get()
+ Flux> result = this.webClient.get()
.uri("/event")
.accept(TEXT_EVENT_STREAM)
.exchange()
diff --git a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java
index 83387cc0a2..252ac12491 100644
--- a/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java
+++ b/spring-web-reactive/src/test/java/org/springframework/web/reactive/result/method/annotation/SseIntegrationTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2016 the original author or authors.
+ * 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.
@@ -35,8 +35,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.DispatcherHandler;
import org.springframework.web.reactive.config.EnableWebReactive;
+import org.springframework.web.reactive.function.client.ExchangeFunction;
+import org.springframework.web.reactive.function.client.ExchangeFunctions;
import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClientOperations;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import org.springframework.web.util.DefaultUriBuilderFactory;
import org.springframework.web.util.UriBuilderFactory;
@@ -55,16 +56,16 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
private AnnotationConfigApplicationContext wac;
- private WebClientOperations operations;
+ private WebClient webClient;
@Override
@Before
public void setup() throws Exception {
super.setup();
- WebClient client = WebClient.create(new ReactorClientHttpConnector());
+ ExchangeFunction exchangeFunction = ExchangeFunctions.create(new ReactorClientHttpConnector());
UriBuilderFactory factory = new DefaultUriBuilderFactory("http://localhost:" + this.port + "/sse");
- this.operations = WebClientOperations.builder(client).uriBuilderFactory(factory).build();
+ this.webClient = WebClient.builder(exchangeFunction).uriBuilderFactory(factory).build();
}
@@ -79,7 +80,7 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
@Test
public void sseAsString() throws Exception {
- Flux result = this.operations.get()
+ Flux result = this.webClient.get()
.uri("/string")
.accept(TEXT_EVENT_STREAM)
.exchange()
@@ -93,7 +94,7 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
}
@Test
public void sseAsPerson() throws Exception {
- Flux result = this.operations.get()
+ Flux result = this.webClient.get()
.uri("/person")
.accept(TEXT_EVENT_STREAM)
.exchange()
@@ -109,7 +110,7 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
@Test
public void sseAsEvent() throws Exception {
ResolvableType type = forClassWithGenerics(ServerSentEvent.class, String.class);
- Flux> result = this.operations.get()
+ Flux> result = this.webClient.get()
.uri("/event")
.accept(TEXT_EVENT_STREAM)
.exchange()
@@ -136,7 +137,7 @@ public class SseIntegrationTests extends AbstractHttpHandlerIntegrationTests {
@Test
public void sseAsEventWithoutAcceptHeader() throws Exception {
- Flux> result = this.operations.get()
+ Flux> result = this.webClient.get()
.uri("/event")
.accept(TEXT_EVENT_STREAM)
.exchange()