diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index eb9a16a..b44059e 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -3,7 +3,7 @@
Spring Cloud is released under the non-restrictive Apache 2.0 license,
and follows a very standard Github development process, using Github
-tracker for issues and merging pull requests into master. If you want
+tracker for issues and merging pull requests into main. If you want
to contribute even something trivial please do not hesitate, but
follow the guidelines below.
@@ -17,7 +17,7 @@ given the ability to merge pull requests.
## Code of Conduct
This project adheres to the Contributor Covenant [code of
-conduct](https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report
+conduct](https://github.com/spring-cloud/spring-cloud-build/blob/main/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report
unacceptable behavior to spring-code-of-conduct@pivotal.io.
## Code Conventions and Housekeeping
@@ -27,7 +27,7 @@ added after the original pull request but before a merge.
* Use the Spring Framework code format conventions. If you use Eclipse
you can import formatter settings using the
`eclipse-code-formatter.xml` file from the
- [Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the
+ [Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the
[Eclipse Code Formatter Plugin](https://plugins.jetbrains.com/plugin/6546) to import the same file.
* Make sure all new `.java` files to have a simple Javadoc class comment with at least an
`@author` tag identifying you, and preferably at least a paragraph on what the class is
@@ -38,7 +38,7 @@ added after the original pull request but before a merge.
than cosmetic changes).
* Add some Javadocs and, if you change the namespace, some XSD doc elements.
* A few unit tests would help a lot as well -- someone has to do it.
-* If no-one else is using your branch, please rebase it against the current master (or
+* If no-one else is using your branch, please rebase it against the current main (or
other target branch in the main project).
* When writing a commit message please follow [these conventions](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html),
if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index ffce470..1e86335 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -5,9 +5,10 @@ name: Build
on:
push:
- branches: [ master ]
+ branches: [ main ]
pull_request:
- branches: [ master ]
+ branches: [ main ]
+
jobs:
build:
@@ -16,7 +17,7 @@ jobs:
strategy:
matrix:
- java: ["8", "15", "16"]
+ java: ["8", "11", "16"]
steps:
- uses: actions/checkout@v2
diff --git a/README.adoc b/README.adoc
index 84aca03..f7cb9d4 100644
--- a/README.adoc
+++ b/README.adoc
@@ -145,7 +145,7 @@ class OkHttpClientConfig {
@Bean
@LoadBalanced
-public WebClient.Builder okHttpClientBuilder() {
+public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
@@ -220,10 +220,10 @@ An application interceptor is added to the `OkHttpClient` created by auto-config
By supporting `OkHttpClient`, it enables Square's [Retrofit](https://square.github.io/retrofit/) to use Spring Cloud LoadBalancer as well.
-See [`OkHttpLoadBalancerInterceptorTests`](https://github.com/spring-cloud-incubator/spring-cloud-square/blob/master/spring-cloud-square-okhttp/src/test/java/org/springframework/cloud/square/okhttp/loadbalancer/OkHttpLoadBalancerInterceptorTests.java) for Spring Cloud LoadBalancer samples.
+See [`OkHttpLoadBalancerInterceptorTests`](https://github.com/spring-cloud-incubator/spring-cloud-square/blob/main/spring-cloud-square-okhttp/src/test/java/org/springframework/cloud/square/okhttp/loadbalancer/OkHttpLoadBalancerInterceptorTests.java) for Spring Cloud LoadBalancer samples.
== Spring WebClient
Support was also added for Spring WebClient. This implements an `okhttp3.Call.Factory` that uses `WebClient` under the covers. This provides a fully non-blocking shim instead of using `okhttp3`.
-See [`WebClientRetrofitTests`](https://github.com/spring-cloud-incubator/spring-cloud-square/blob/master/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitTests.java) for WebClient samples.
+See [`WebClientRetrofitTests`](https://github.com/spring-cloud-incubator/spring-cloud-square/blob/main/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitTests.java) for WebClient samples.
diff --git a/docs/src/main/asciidoc/README.adoc b/docs/src/main/asciidoc/README.adoc
index 40e3372..afa1065 100644
--- a/docs/src/main/asciidoc/README.adoc
+++ b/docs/src/main/asciidoc/README.adoc
@@ -14,10 +14,10 @@ An application interceptor is added to the `OkHttpClient` created by auto-config
By supporting `OkHttpClient`, it enables Square's [Retrofit](https://square.github.io/retrofit/) to use Spring Cloud LoadBalancer as well.
-See [`OkHttpLoadBalancerInterceptorTests`](https://github.com/spring-cloud-incubator/spring-cloud-square/blob/master/spring-cloud-square-okhttp/src/test/java/org/springframework/cloud/square/okhttp/loadbalancer/OkHttpLoadBalancerInterceptorTests.java) for Spring Cloud LoadBalancer samples.
+See [`OkHttpLoadBalancerInterceptorTests`](https://github.com/spring-cloud-incubator/spring-cloud-square/blob/main/spring-cloud-square-okhttp/src/test/java/org/springframework/cloud/square/okhttp/loadbalancer/OkHttpLoadBalancerInterceptorTests.java) for Spring Cloud LoadBalancer samples.
== Spring WebClient
Support was also added for Spring WebClient. This implements an `okhttp3.Call.Factory` that uses `WebClient` under the covers. This provides a fully non-blocking shim instead of using `okhttp3`.
-See [`WebClientRetrofitTests`](https://github.com/spring-cloud-incubator/spring-cloud-square/blob/master/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitTests.java) for WebClient samples.
+See [`WebClientRetrofitTests`](https://github.com/spring-cloud-incubator/spring-cloud-square/blob/main/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitTests.java) for WebClient samples.
diff --git a/docs/src/main/asciidoc/_attributes.adoc b/docs/src/main/asciidoc/_attributes.adoc
index a65926b..8367294 100644
--- a/docs/src/main/asciidoc/_attributes.adoc
+++ b/docs/src/main/asciidoc/_attributes.adoc
@@ -12,5 +12,5 @@
:docinfo: shared,private
:sc-ext: java
-:project-full-name: Spring Cloud Commons
-:all: {asterisk}{asterisk}
\ No newline at end of file
+:project-full-name: Spring Cloud Square
+:all: {asterisk}{asterisk}
diff --git a/docs/src/main/asciidoc/ghpages.sh b/docs/src/main/asciidoc/ghpages.sh
index d18aa88..f35e9e8 100755
--- a/docs/src/main/asciidoc/ghpages.sh
+++ b/docs/src/main/asciidoc/ghpages.sh
@@ -39,7 +39,7 @@ function check_if_anything_to_sync() {
}
function retrieve_current_branch() {
- # Code getting the name of the current branch. For master we want to publish as we did until now
+ # Code getting the name of the current branch. For main we want to publish as we did until now
# https://stackoverflow.com/questions/1593051/how-to-programmatically-determine-the-current-checked-out-git-branch
# If there is a branch already passed will reuse it - otherwise will try to find it
CURRENT_BRANCH=${BRANCH}
@@ -134,8 +134,8 @@ function add_docs_from_target() {
# Copies the docs by using the retrieved properties from Maven build
function copy_docs_for_current_version() {
- if [[ "${CURRENT_BRANCH}" == "master" ]] ; then
- echo -e "Current branch is master - will copy the current docs only to the root folder"
+ if [[ "${CURRENT_BRANCH}" == "main" ]] ; then
+ echo -e "Current branch is main - will copy the current docs only to the root folder"
for f in docs/target/generated-docs/*; do
file=${f#docs/target/generated-docs/*}
if ! git ls-files -i -o --exclude-standard --directory | grep -q ^$file$; then
@@ -216,7 +216,7 @@ function commit_changes_if_applicable() {
git commit -a -m "Sync docs from ${CURRENT_BRANCH} to gh-pages" && COMMIT_SUCCESSFUL="yes" || echo "Failed to commit changes"
# Uncomment the following push if you want to auto push to
- # the gh-pages branch whenever you commit to master locally.
+ # the gh-pages branch whenever you commit to main locally.
# This is a little extreme. Use with care!
###################################################################
if [[ "${COMMIT_SUCCESSFUL}" == "yes" ]] ; then
@@ -249,7 +249,7 @@ The idea of this script is to update gh-pages branch with the generated docs. Wi
the script will work in the following manner:
- if there's no gh-pages / target for docs module then the script ends
-- for master branch the generated docs are copied to the root of gh-pages branch
+- for main branch the generated docs are copied to the root of gh-pages branch
- for any other branch (if that branch is allowed) a subfolder with branch name is created
and docs are copied there
- if the version switch is passed (-v) then a tag with (v) prefix will be retrieved and a folder
diff --git a/docs/src/main/asciidoc/quickstart.adoc b/docs/src/main/asciidoc/quickstart.adoc
index 2257bea..5f77e80 100644
--- a/docs/src/main/asciidoc/quickstart.adoc
+++ b/docs/src/main/asciidoc/quickstart.adoc
@@ -130,7 +130,7 @@ class OkHttpClientConfig {
@Bean
@LoadBalanced
-public WebClient.Builder okHttpClientBuilder() {
+public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
diff --git a/docs/src/main/asciidoc/spring-cloud-square.adoc b/docs/src/main/asciidoc/spring-cloud-square.adoc
index 0881595..612c8f4 100644
--- a/docs/src/main/asciidoc/spring-cloud-square.adoc
+++ b/docs/src/main/asciidoc/spring-cloud-square.adoc
@@ -6,12 +6,12 @@ include::intro.adoc[]
NOTE: Spring Cloud is released under the non-restrictive Apache 2.0 license.
If you want to contribute to this section of the documentation or if you find an error, you can find the source code and issue trackers for the project at {docslink}[github].
+Spring Cloud Square provides Spring Cloud LoadBalancer integration for https://square.github.io/okhttp/[OkHttpClient] and https://square.github.io/retrofit/[Retrofit], as well as a WebClient-backed Retrofit clients.
+
== Quick Start
include::quickstart.adoc[leveloffset=+1]
-Spring Cloud Square provides Spring Cloud LoadBalancer integration for https://square.github.io/okhttp/[OkHttpClient] and https://square.github.io/retrofit/[Retrofit], as well as a WebClient-backed Retrofit clients.
-
== OkHttpClient Spring Cloud LoadBalancer Integration
An interceptor is added to the `OkHttpClient` created by auto-configuration to resolve the scheme, host, and port from Spring Cloud LoadBalancer and rewrite the URL.
@@ -149,7 +149,7 @@ class OkHttpClientConfig {
@Bean
@LoadBalanced
-public WebClient.Builder okHttpClientBuilder() {
+public WebClient.Builder webClientBuilder() {
return WebClient.builder();
}
}
@@ -157,6 +157,8 @@ public WebClient.Builder okHttpClientBuilder() {
They are used under the hood to run load-balanced HTTP requests.
+NOTE: You can create various instances of `WebClient.Builder` with different setup. If a `@LoadBalanced WebClient.Builder` bean is found with name matching the pattern `[retrofit-context-name]WebClientBuilder`, it will be picked for the Retrofit context in question, otherwise the first found `@LoadBalaced WebClient.Builder` bean will be picked.
+
=== Retrofit Reactor support
diff --git a/pom.xml b/pom.xml
index 2e1d18e..f2f05d5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -14,15 +14,16 @@
org.springframework.cloud
spring-cloud-build
- 3.0.3-SNAPSHOT
+ 3.1.0-SNAPSHOT
UTF-8
- 3.0.3-SNAPSHOT
+ 3.1.0-SNAPSHOT
+
-
+
diff --git a/spring-cloud-square-dependencies/pom.xml b/spring-cloud-square-dependencies/pom.xml
index 0fea40a..3f17a4a 100644
--- a/spring-cloud-square-dependencies/pom.xml
+++ b/spring-cloud-square-dependencies/pom.xml
@@ -6,7 +6,7 @@
spring-cloud-dependencies-parent
org.springframework.cloud
- 3.0.2
+ 3.1.0-SNAPSHOT
spring-cloud-square-dependencies
diff --git a/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/AbstractRetrofitClientsRegistrar.java b/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/AbstractRetrofitClientsRegistrar.java
index fc9fb0d..ae33b05 100644
--- a/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/AbstractRetrofitClientsRegistrar.java
+++ b/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/AbstractRetrofitClientsRegistrar.java
@@ -17,7 +17,6 @@
package org.springframework.cloud.square.retrofit.core;
import java.io.IOException;
-import java.lang.annotation.Annotation;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
@@ -66,9 +65,6 @@ public abstract class AbstractRetrofitClientsRegistrar
private ClassLoader classLoader;
- public AbstractRetrofitClientsRegistrar() {
- }
-
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
@@ -257,26 +253,13 @@ protected ClassPathScanningCandidateComponentProvider getScanner() {
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
+ boolean isCandidate = false;
if (beanDefinition.getMetadata().isIndependent()) {
- // TODO until SPR-11711 will be resolved
- if (beanDefinition.getMetadata().isInterface()
- && beanDefinition.getMetadata().getInterfaceNames().length == 1
- && Annotation.class.getName().equals(beanDefinition.getMetadata().getInterfaceNames()[0])) {
- try {
- Class> target = ClassUtils.forName(beanDefinition.getMetadata().getClassName(),
- AbstractRetrofitClientsRegistrar.this.classLoader);
- return !target.isAnnotation();
- }
- catch (Exception ex) {
- this.logger.error(
- "Could not load target class: " + beanDefinition.getMetadata().getClassName(), ex);
-
- }
+ if (!beanDefinition.getMetadata().isAnnotation()) {
+ isCandidate = true;
}
- return true;
}
- return false;
-
+ return isCandidate;
}
};
}
diff --git a/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/RetrofitClient.java b/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/RetrofitClient.java
index 7fd70ea..d806b19 100644
--- a/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/RetrofitClient.java
+++ b/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/RetrofitClient.java
@@ -23,6 +23,7 @@
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
+import org.springframework.stereotype.Indexed;
/**
* Annotation for interfaces declaring that a REST client with that interface should be
@@ -36,6 +37,7 @@
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
+@Indexed
public @interface RetrofitClient {
/**
diff --git a/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/RetrofitClientSpecification.java b/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/RetrofitClientSpecification.java
index 4eb1b59..8129f22 100644
--- a/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/RetrofitClientSpecification.java
+++ b/spring-cloud-square-retrofit-core/src/main/java/org/springframework/cloud/square/retrofit/core/RetrofitClientSpecification.java
@@ -33,9 +33,7 @@ public class RetrofitClientSpecification implements NamedContextFactory.Specific
public RetrofitClientSpecification(String name, Class>[] configuration) {
this.name = name;
this.configuration = configuration;
- }
- public RetrofitClientSpecification() {
}
public String getName() {
@@ -68,7 +66,7 @@ public boolean equals(Object o) {
@Override
public int hashCode() {
- return Objects.hash(name, configuration);
+ return Objects.hash(name, Arrays.hashCode(configuration));
}
@Override
diff --git a/spring-cloud-square-retrofit-webclient/pom.xml b/spring-cloud-square-retrofit-webclient/pom.xml
index fe609e0..f9d3f4b 100644
--- a/spring-cloud-square-retrofit-webclient/pom.xml
+++ b/spring-cloud-square-retrofit-webclient/pom.xml
@@ -60,6 +60,11 @@
spring-boot-starter-test
test
+
+ io.projectreactor
+ reactor-test
+ test
+
diff --git a/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/EnableRetrofitClients.java b/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/EnableRetrofitClients.java
index 4f1e631..105a2d0 100644
--- a/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/EnableRetrofitClients.java
+++ b/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/EnableRetrofitClients.java
@@ -81,7 +81,7 @@
/**
* List of classes annotated with @RetrofitClient. If not empty, disables classpath
* scanning.
- * @return
+ * @return an array of {@link RetrofitClient}-annotated classes
*/
Class>[] clients() default {};
diff --git a/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/WebClientCallAdapterFactory.java b/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/WebClientCallAdapterFactory.java
index bed1d92..4230c1d 100644
--- a/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/WebClientCallAdapterFactory.java
+++ b/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/WebClientCallAdapterFactory.java
@@ -16,13 +16,22 @@
package org.springframework.cloud.square.retrofit.webclient;
+import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;
+import okhttp3.MediaType;
import okhttp3.Request;
+import okhttp3.RequestBody;
+import okio.Buffer;
+import okio.BufferedSink;
+import okio.Okio;
+import okio.Sink;
+import okio.Timeout;
+import org.reactivestreams.Publisher;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import retrofit2.Call;
@@ -34,6 +43,12 @@
import org.springframework.web.reactive.function.client.ClientResponse;
import org.springframework.web.reactive.function.client.WebClient;
+/**
+ * {@link WebClient}-specific {@link CallAdapter.Factory} implementation.
+ *
+ * @author Spencer Gibb
+ * @author Olga Maciaszek-Sharma
+ */
public class WebClientCallAdapterFactory extends CallAdapter.Factory {
public WebClientCallAdapterFactory() {
@@ -125,11 +140,50 @@ WebClient.RequestBodySpec requestBuilder(WebClient webClient, Request request) {
httpHeaders.put(entry.getKey(), entry.getValue());
}
});
- if (request.body() != null) {
- // spec.body()
- // FIXME: body
+ RequestBody requestBody = request.body();
+ if (requestBody != null) {
+ processRequestBody(spec, requestBody);
}
return spec;
}
+ private void processRequestBody(WebClient.RequestBodySpec spec, RequestBody requestBody) {
+ Publisher requestBodyPublisher = Flux.create(sink -> {
+ try {
+ Sink fluxSink = new Sink() {
+ @Override
+ public void write(Buffer source, long byteCount) throws IOException {
+ sink.next(source.readByteArray(byteCount));
+ }
+
+ @Override
+ public void flush() {
+ sink.complete();
+ }
+
+ @Override
+ public Timeout timeout() {
+ return Timeout.NONE;
+ }
+
+ @Override
+ public void close() {
+ sink.complete();
+ }
+ };
+ BufferedSink bufferedSink = Okio.buffer(fluxSink);
+ requestBody.writeTo(bufferedSink);
+ bufferedSink.flush();
+ }
+ catch (IOException e) {
+ sink.error(e);
+ }
+ });
+ spec.body(requestBodyPublisher, byte[].class);
+ MediaType requestContentType = requestBody.contentType();
+ if (requestContentType != null) {
+ spec.contentType(org.springframework.http.MediaType.parseMediaType(requestContentType.toString()));
+ }
+ }
+
}
diff --git a/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitClientFactoryBean.java b/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitClientFactoryBean.java
index a0d8318..d62bb02 100644
--- a/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitClientFactoryBean.java
+++ b/spring-cloud-square-retrofit-webclient/src/main/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitClientFactoryBean.java
@@ -16,7 +16,9 @@
package org.springframework.cloud.square.retrofit.webclient;
+import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
import retrofit2.Retrofit;
@@ -26,10 +28,15 @@
import org.springframework.web.reactive.function.client.WebClient;
/**
+ * {@link WebClient}-specific {@link AbstractRetrofitClientFactoryBean} implementation.
+ *
* @author Spencer Gibb
+ * @author Olga Maciaszek-Sharma
*/
public class WebClientRetrofitClientFactoryBean extends AbstractRetrofitClientFactoryBean {
+ private static final String WEB_CLIENT_BUILDER_SUFFIX = "WebClientBuilder";
+
/***********************************
* WARNING! Nothing in this class should be @Autowired. It causes NPEs because of some
* lifecycle race condition.
@@ -64,19 +71,24 @@ protected Retrofit.Builder retrofit(RetrofitContext context, boolean hasUrl) {
protected Object loadBalance(Retrofit.Builder builder, RetrofitContext context, String serviceIdUrl) {
Map instances = context.getInstances(this.name, WebClient.Builder.class);
- for (Map.Entry entry : instances.entrySet()) {
- String beanName = entry.getKey();
- WebClient.Builder clientBuilder = entry.getValue();
-
- if (applicationContext.findAnnotationOnBean(beanName, LoadBalanced.class) != null) {
- builder.callFactory(new WebClientCallFactory(clientBuilder.build()));
- Retrofit retrofit = buildAndSave(context, builder);
- return retrofit.create(this.type);
- }
+ List> loadBalancedWebClientBuilders = instances.entrySet().stream()
+ .filter(entry -> applicationContext.findAnnotationOnBean(entry.getKey(), LoadBalanced.class) != null)
+ .collect(Collectors.toList());
+ if (loadBalancedWebClientBuilders.isEmpty()) {
+ throw new IllegalStateException(
+ "No WebClient.Builder for loadBalancing defined. Did you forget to include spring-cloud-loadbalancer?");
}
+ WebClient.Builder selectedWebClientBuilder = loadBalancedWebClientBuilders.stream()
+ .filter(entry -> entry.getKey().equals(name + WEB_CLIENT_BUILDER_SUFFIX)).findAny()
+ .orElse(loadBalancedWebClientBuilders.stream().findAny().get()).getValue();
+ return buildRetrofit(builder, context, selectedWebClientBuilder);
+ }
- throw new IllegalStateException(
- "No WebClient.Builder for loadBalancing defined. Did you forget to include spring-cloud-loadbalancer?");
+ private Object buildRetrofit(Retrofit.Builder builder, RetrofitContext context,
+ WebClient.Builder loadBalancedWebClientBuilder) {
+ builder.callFactory(new WebClientCallFactory(loadBalancedWebClientBuilder.build()));
+ Retrofit retrofit = buildAndSave(context, builder);
+ return retrofit.create(this.type);
}
}
diff --git a/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitLoadBalancerTests.java b/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitLoadBalancerTests.java
index b28109c..f759b9c 100644
--- a/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitLoadBalancerTests.java
+++ b/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitLoadBalancerTests.java
@@ -31,6 +31,7 @@
import org.springframework.cloud.client.DefaultServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient;
+import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClients;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.cloud.loadbalancer.support.ServiceInstanceListSuppliers;
import org.springframework.cloud.square.retrofit.core.RetrofitClient;
@@ -43,6 +44,7 @@
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;
/**
@@ -61,6 +63,9 @@ class WebClientRetrofitLoadBalancerTests {
@Autowired
private TestClient testClient;
+ @Autowired
+ TestClientWithCustomWebClientBuilder testClientWithCustomWebClientBuilder;
+
@Autowired
private RetrofitContext retrofitContext;
@@ -79,6 +84,12 @@ void testSimpleType() {
assertThat(response).isEqualTo(new Hello(HELLO_WORLD_1));
}
+ @Test
+ void testCustomWebClientBuilderPickeByRetrofitName() {
+ assertThatExceptionOfType(UnsupportedOperationException.class)
+ .isThrownBy(() -> testClientWithCustomWebClientBuilder.getHello().block());
+ }
+
@RetrofitClient("localapp")
protected interface TestClient {
@@ -87,10 +98,19 @@ protected interface TestClient {
}
+ @RetrofitClient("localapp2")
+ protected interface TestClientWithCustomWebClientBuilder {
+
+ @GET("/hello")
+ Mono getHello();
+
+ }
+
@SpringBootConfiguration
@EnableAutoConfiguration
- @EnableRetrofitClients(clients = TestClient.class)
- @LoadBalancerClient(name = "localapp", configuration = TestAppConfig.class)
+ @EnableRetrofitClients(clients = { TestClient.class, TestClientWithCustomWebClientBuilder.class })
+ @LoadBalancerClients({ @LoadBalancerClient(name = "localapp", configuration = TestAppConfig.class),
+ @LoadBalancerClient(name = "localapp2", configuration = TestAppConfig.class) })
@SuppressWarnings("unused")
@RestController
protected static class Application {
@@ -106,6 +126,14 @@ public WebClient.Builder builder() {
return WebClient.builder();
}
+ @Bean
+ @LoadBalanced
+ public WebClient.Builder localapp2WebClientBuilder() {
+ return WebClient.builder().filter((request, next) -> {
+ throw new UnsupportedOperationException("Failing WebClient Instance");
+ });
+ }
+
}
protected static class TestAppConfig {
diff --git a/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitTests.java b/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitTests.java
index e36b32e..bccc973 100644
--- a/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitTests.java
+++ b/spring-cloud-square-retrofit-webclient/src/test/java/org/springframework/cloud/square/retrofit/webclient/WebClientRetrofitTests.java
@@ -16,13 +16,18 @@
package org.springframework.cloud.square.retrofit.webclient;
+import java.util.Objects;
+
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
+import retrofit2.http.Body;
import retrofit2.http.GET;
+import retrofit2.http.POST;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringBootConfiguration;
@@ -31,9 +36,12 @@
import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cloud.square.retrofit.core.RetrofitClient;
import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.util.SocketUtils;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@@ -116,6 +124,12 @@ void webClientSimple() {
assertThat(hello).isEqualTo(HELLO);
}
+ @Test
+ void webClientWithPayload() {
+ StepVerifier.create(testClient.withPayload("Hello World"))
+ .assertNext(response -> assertThat(response.statusCode().is2xxSuccessful()).isTrue()).verifyComplete();
+ }
+
private TestClient testClient() {
return testClient;
/*
@@ -153,6 +167,9 @@ protected interface TestClient {
@GET("/hellos")
Flux getHellosFlux();
+ @POST("/hello")
+ Mono withPayload(@Body String payload);
+
}
@SpringBootConfiguration
@@ -171,6 +188,17 @@ public Flux getHellos() {
return Flux.just(HELLO, "hi");
}
+ @RequestMapping(method = RequestMethod.POST, path = "/hello")
+ public Mono withPayload(@RequestBody(required = false) String payload,
+ @RequestHeader(value = "Content-Type", required = false) MediaType contentType) {
+ Objects.requireNonNull(payload, "Payload can not be null");
+ Objects.requireNonNull(contentType, "Content type can not be null");
+ if (!payload.equals("Hello World") || !contentType.toString().equals("text/plain;charset=UTF-8")) {
+ throw new IllegalArgumentException("Body was not processed correctly!");
+ }
+ return Mono.empty();
+ }
+
}
}
diff --git a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/DefaultRetrofitClientConfiguration.java b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/DefaultRetrofitClientConfiguration.java
index f48c3b3..64175b3 100644
--- a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/DefaultRetrofitClientConfiguration.java
+++ b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/DefaultRetrofitClientConfiguration.java
@@ -16,8 +16,9 @@
package org.springframework.cloud.square.retrofit;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.List;
+import java.util.stream.Collectors;
import com.jakewharton.retrofit2.adapter.reactor.ReactorCallAdapterFactory;
import okhttp3.Interceptor;
@@ -28,7 +29,7 @@
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.ObjectFactory;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -45,13 +46,11 @@
/**
* @author Dave Syer
* @author Olga Maciaszek-Sharma
+ * @author Josh Long
*/
-@Configuration
+@Configuration(proxyBeanMethods = false)
public class DefaultRetrofitClientConfiguration {
- @Autowired
- private ObjectFactory messageConverters;
-
@Bean
@Scope("prototype")
@ConditionalOnMissingBean
@@ -67,26 +66,26 @@ public DefaultFormattingConversionService retrofitConversionService() {
@Bean
@ConditionalOnMissingBean(ConverterFactory.class)
- public SpringConverterFactory springConverterFactory(ConversionService conversionService) {
+ public SpringConverterFactory springConverterFactory(ObjectFactory messageConverters,
+ ConversionService conversionService) {
return new SpringConverterFactory(messageConverters, conversionService);
}
- @Configuration
- protected static class DefaultOkHttpConfiguration {
-
- @Autowired(required = false)
- private List httpClientBuilders = Collections.emptyList();
+ @Configuration(proxyBeanMethods = false)
+ public static class DefaultOkHttpConfiguration {
// TODO move to abstract class in core module?
@Bean
- public InitializingBean okHttpClientBuilderInitializer(final List customizers) {
- return () -> {
- for (OkHttpClient.Builder builder : DefaultOkHttpConfiguration.this.httpClientBuilders) {
- for (OkHttpClientBuilderCustomizer customizer : customizers) {
- customizer.accept(builder);
- }
- }
- };
+ public RetrofitClientBuilderInitializer okHttpClientBuilderInitializer(
+ ObjectProvider provider, List customizers) {
+ List builders;
+ if (provider.iterator().hasNext()) {
+ builders = provider.stream().collect(Collectors.toList());
+ }
+ else {
+ builders = new ArrayList<>();
+ }
+ return new RetrofitClientBuilderInitializer(customizers, builders);
}
@Bean
@@ -97,20 +96,41 @@ public OkHttpClientBuilderCustomizer okHttpClientBuilderCustomizer(List customizers;
+
+ private final List httpClientBuilders;
+
+ public RetrofitClientBuilderInitializer(List customizers,
+ List httpClientBuilders) {
+ this.customizers = customizers;
+ this.httpClientBuilders = httpClientBuilders;
+ }
+
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ for (OkHttpClient.Builder builder : this.httpClientBuilders) {
+ for (OkHttpClientBuilderCustomizer customizer : customizers) {
+ customizer.accept(builder);
+ }
+ }
+ }
+
+ }
+
}
- @Configuration
+ @Configuration(proxyBeanMethods = false)
@ConditionalOnClass(ReactorCallAdapterFactory.class)
@ConditionalOnProperty(value = "retrofit.reactor.enabled", matchIfMissing = true)
protected static class RetrofitReactorConfiguration {
- @Autowired(required = false)
- private Scheduler scheduler;
-
@Bean
@ConditionalOnMissingBean(CallAdapter.Factory.class)
- public ReactorCallAdapterFactory reactorCallAdapterFactory() {
- if (this.scheduler != null) {
+ public ReactorCallAdapterFactory reactorCallAdapterFactory(ObjectProvider provider) {
+ Scheduler scheduler = provider.getIfAvailable();
+ if (scheduler != null) {
return ReactorCallAdapterFactory.createWithScheduler(scheduler);
}
return ReactorCallAdapterFactory.create();
diff --git a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/EnableRetrofitClients.java b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/EnableRetrofitClients.java
index 7b87f48..b1cced9 100644
--- a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/EnableRetrofitClients.java
+++ b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/EnableRetrofitClients.java
@@ -22,6 +22,7 @@
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
+import org.springframework.cloud.square.retrofit.core.RetrofitClient;
import org.springframework.context.annotation.Import;
/**
@@ -78,9 +79,9 @@
Class>[] defaultConfiguration() default {};
/**
- * List of classes annotated with @RetrofitClient. If not empty, disables classpath
- * scanning.
- * @return
+ * List of classes annotated with {@link RetrofitClient}. If not empty, disables
+ * classpath scanning.
+ * @return an array of {@link RetrofitClient}-annotated classes
*/
Class>[] clients() default {};
diff --git a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitAutoConfiguration.java b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitAutoConfiguration.java
index 43c654b..df7f80b 100644
--- a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitAutoConfiguration.java
+++ b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitAutoConfiguration.java
@@ -16,12 +16,11 @@
package org.springframework.cloud.square.retrofit;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.stream.Collectors;
import retrofit2.Retrofit;
-import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.cloud.client.actuator.HasFeatures;
@@ -33,23 +32,20 @@
/**
* @author Spencer Gibb
*/
-@Configuration
+@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Retrofit.class)
@ConditionalOnBean(RetrofitConfiguration.Marker.class)
public class RetrofitAutoConfiguration {
- @Autowired(required = false)
- private List configurations = new ArrayList<>();
-
@Bean
public HasFeatures retrofitFeature() {
return HasFeatures.namedFeature("Retrofit", Retrofit.class);
}
@Bean
- public RetrofitContext retrofitContext() {
+ public RetrofitContext retrofitContext(ObjectProvider clientSpecifications) {
RetrofitContext context = new RetrofitContext(DefaultRetrofitClientConfiguration.class);
- context.setConfigurations(this.configurations);
+ context.setConfigurations(clientSpecifications.stream().collect(Collectors.toList()));
return context;
}
diff --git a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitClientFactoryBean.java b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitClientFactoryBean.java
index b5c9668..75c4b1e 100644
--- a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitClientFactoryBean.java
+++ b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitClientFactoryBean.java
@@ -51,7 +51,6 @@ protected Object loadBalance(Retrofit.Builder builder, RetrofitContext context,
for (Map.Entry entry : instances.entrySet()) {
String beanName = entry.getKey();
OkHttpClient.Builder clientBuilder = entry.getValue();
-
if (applicationContext.findAnnotationOnBean(beanName, LoadBalanced.class) != null) {
builder.client(clientBuilder.build());
Retrofit retrofit = buildAndSave(context, builder);
diff --git a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitConfiguration.java b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitConfiguration.java
index cc6276a..e3b1cee 100644
--- a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitConfiguration.java
+++ b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/RetrofitConfiguration.java
@@ -30,7 +30,7 @@ public Marker retrofitConfigurationMarker() {
return new Marker();
}
- class Marker {
+ public static class Marker {
}
diff --git a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/support/SpringConverterFactory.java b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/support/SpringConverterFactory.java
index 6caa0f1..71a4ce0 100644
--- a/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/support/SpringConverterFactory.java
+++ b/spring-cloud-square-retrofit/src/main/java/org/springframework/cloud/square/retrofit/support/SpringConverterFactory.java
@@ -43,7 +43,7 @@ public class SpringConverterFactory extends Converter.Factory {
private final ConversionService conversionService;
- private ObjectFactory messageConverters;
+ private final ObjectFactory messageConverters;
public SpringConverterFactory(ObjectFactory messageConverters,
ConversionService conversionService) {
@@ -57,7 +57,7 @@ public SpringConverterFactory(ObjectFactory messageConver
if (type instanceof Class || type instanceof ParameterizedType) {
// MediaType contentType = getContentType(responseWrapper);
MediaType contentType = MediaType.APPLICATION_JSON; // TODO: determine
- // dynamically?
+ // dynamically?
Class> responseClass = (type instanceof Class) ? (Class>) type : null;
for (HttpMessageConverter> messageConverter : this.messageConverters.getObject().getConverters()) {
@@ -89,7 +89,7 @@ public SpringConverterFactory(ObjectFactory messageConver
public Converter, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations,
Annotation[] methodAnnotations, Retrofit retrofit) {
MediaType requestContentType = MediaType.APPLICATION_JSON; // TODO: determine
- // dynamically?
+ // dynamically?
if (type instanceof Class) {
Class> requestType = (Class>) type;
diff --git a/spring-cloud-square-retrofit/src/test/java/org/springframework/cloud/square/retrofit/RetrofitClientUrlTests.java b/spring-cloud-square-retrofit/src/test/java/org/springframework/cloud/square/retrofit/RetrofitClientUrlTests.java
index 004d6d8..1f72a59 100644
--- a/spring-cloud-square-retrofit/src/test/java/org/springframework/cloud/square/retrofit/RetrofitClientUrlTests.java
+++ b/spring-cloud-square-retrofit/src/test/java/org/springframework/cloud/square/retrofit/RetrofitClientUrlTests.java
@@ -16,6 +16,7 @@
package org.springframework.cloud.square.retrofit;
+import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
@@ -29,6 +30,8 @@
import retrofit2.Call;
import retrofit2.Response;
import retrofit2.http.Body;
+import retrofit2.http.Field;
+import retrofit2.http.FormUrlEncoded;
import retrofit2.http.GET;
import retrofit2.http.HEAD;
import retrofit2.http.Header;
@@ -91,6 +94,7 @@ void testClient() {
@Test
void testDynamicUrl() throws Exception {
Response response = testClient.getHelloWithDynamicUrl(urlAsSpringProperty).execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
Hello hello = response.body();
assertThat(hello).withFailMessage("hello was null").isNotNull();
@@ -100,6 +104,7 @@ void testDynamicUrl() throws Exception {
@Test
void testSimpleType() throws Exception {
Response response = testClient.getHello().execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
Hello hello = response.body();
assertThat(hello).withFailMessage("hello was null").isNotNull();
@@ -109,6 +114,7 @@ void testSimpleType() throws Exception {
@Test
void testSimpleTypeBody() throws Exception {
Response response = testClient.postHello(new Hello("postHello")).execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
Hello hello = response.body();
assertThat(hello).withFailMessage("hello was null").isNotNull();
@@ -118,6 +124,7 @@ void testSimpleTypeBody() throws Exception {
@Test
void testGenericType() throws Exception {
Response> response = testClient.getHellos().execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
List hellos = response.body();
assertThat(hellos).isNotNull();
@@ -127,6 +134,7 @@ void testGenericType() throws Exception {
@Test
void testRequestInterceptors() throws Exception {
Response> response = testClient.getHelloHeaders().execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
List headers = response.body();
assertThat(headers).withFailMessage("headers was null").isNotNull();
@@ -137,6 +145,7 @@ void testRequestInterceptors() throws Exception {
@Test
void testDynamicHeaders() throws Exception {
Response response = testClient.getDynamicHeader(myDynamicHeader).execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
String header = response.body();
assertThat(header).withFailMessage("headers was null").isNotNull();
@@ -146,6 +155,7 @@ void testDynamicHeaders() throws Exception {
@Test
void testParams() throws Exception {
Response> response = testClient.getParams("a", "1", "test").execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
List params = response.body();
assertThat(params).withFailMessage("params was null").isNotNull();
@@ -155,6 +165,7 @@ void testParams() throws Exception {
@Test
void testNoContentResponse() throws Exception {
Response response = testClient.noContent().execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
assertThat(response).withFailMessage("response was null").isNotNull();
assertThat(response.code()).withFailMessage("status code was wrong").isEqualTo(HttpStatus.NO_CONTENT.value());
@@ -163,6 +174,7 @@ void testNoContentResponse() throws Exception {
@Test
void testHeadResponse() throws Exception {
Response response = testClient.head().execute();
+
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
assertThat(response).withFailMessage("response was null").isNotNull();
assertThat(response.code()).withFailMessage("status code was wrong").isEqualTo(HttpStatus.OK.value());
@@ -172,6 +184,7 @@ void testHeadResponse() throws Exception {
void testMoreComplexHeader() throws Exception {
String body = "{\"value\":\"OK\"}";
Response response = testClient.moreComplexContentType(body).execute();
+
assertThat(response).withFailMessage("response was null").isNotNull();
assertThat(response.isSuccessful()).withFailMessage("response was unsuccessful " + response.code()).isTrue();
assertThat(response.body()).withFailMessage("response was incorrect").isEqualTo(body);
@@ -186,9 +199,17 @@ void testEnumAsQueryParam() throws Exception {
@Test
void testObjectAsQueryParam() throws Exception {
Response response = testClient.getToString(new OtherArg("foo")).execute();
+
assertThat(response.body()).isEqualTo("foo");
}
+ @Test
+ void testPostWithParam() throws IOException {
+ Response response = testClient.postParams("testValue").execute();
+
+ assertThat(response.body()).isEqualTo("testValue");
+ }
+
protected enum Arg {
A, B;
@@ -243,6 +264,10 @@ protected interface TestClient {
@GET("/tostring2")
Call getToString(@Query("arg") OtherArg arg);
+ @POST("/postParams")
+ @FormUrlEncoded
+ Call postParams(@Field("param") String paramValue);
+
}
protected static class OtherArg {
@@ -326,6 +351,11 @@ String getToString(@RequestParam("arg") OtherArg arg) {
return arg.value;
}
+ @PostMapping("/postParams")
+ String postParams(@RequestParam("param") String paramValue) {
+ return paramValue;
+ }
+
}
}