Skip to content

Commit

Permalink
Merge pull request #32857 from Sgitario/32189_new
Browse files Browse the repository at this point in the history
Provide new API to programmatically create REST Client reactive
  • Loading branch information
geoand authored Apr 25, 2023
2 parents e24fc66 + e3e4488 commit 585ebb2
Show file tree
Hide file tree
Showing 23 changed files with 521 additions and 84 deletions.
46 changes: 39 additions & 7 deletions docs/src/main/asciidoc/rest-client-reactive.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -351,11 +351,11 @@ There are two interesting parts in this listing:

<1> the client stub is injected with the `@RestClient` annotation instead of the usual CDI `@Inject`

== Programmatic client creation with RestClientBuilder
== Programmatic client creation with QuarkusRestClientBuilder

Instead of annotating the client with `@RegisterRestClient`, and injecting
a client with `@RestClient`, you can also create REST Client programmatically.
You do that with `RestClientBuilder`.
You do that with the `QuarkusRestClientBuilder`.

With this approach the client interface could look as follows:

Expand All @@ -381,7 +381,7 @@ And the service as follows:
----
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
Expand All @@ -394,7 +394,7 @@ public class ExtensionsResource {
private final ExtensionsService extensionsService;
public ExtensionsResource() {
extensionsService = RestClientBuilder.newBuilder()
extensionsService = QuarkusRestClientBuilder.newBuilder()
.baseUri(URI.create("https://stage.code.quarkus.io/api"))
.build(ExtensionsService.class);
}
Expand All @@ -407,6 +407,38 @@ public class ExtensionsResource {
}
----

[TIP]
====
The `QuarkusRestClientBuilder` interface is a Quarkus-specific API to programmatically create clients with additional configuration options. Otherwise, you can also use the `RestClientBuilder` interface from the Microprofile API:
[source,java]
----
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import java.net.URI;
import java.util.Set;
@Path("/extension")
public class ExtensionsResource {
private final ExtensionsService extensionsService;
public ExtensionsResource() {
extensionsService = RestClientBuilder.newBuilder()
.baseUri(URI.create("https://stage.code.quarkus.io/api"))
.build(ExtensionsService.class);
}
// ...
}
----
====

== Use Custom HTTP Options

The REST Client Reactive internally uses https://vertx.io/docs/apidocs/io/vertx/core/http/HttpClient.html[the Vert.x HTTP Client] to make the network connections. The REST Client Reactive extensions allows configuring some settings via properties, for example:
Expand Down Expand Up @@ -450,7 +482,7 @@ Another approach is to provide the custom HTTP Client options when creating the
----
package org.acme.rest.client;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
Expand All @@ -465,7 +497,7 @@ public class ExtensionsResource {
private final ExtensionsService extensionsService;
public ExtensionsResource() {
extensionsService = RestClientBuilder.newBuilder()
extensionsService = QuarkusRestClientBuilder.newBuilder()
.baseUri(URI.create("https://stage.code.quarkus.io/api"))
.register(CustomHttpClientOptions.class) <1>
.build(ExtensionsService.class);
Expand Down Expand Up @@ -562,7 +594,7 @@ public class ExtensionsResource {
private final ExtensionsService extensionsService;
public ExtensionsResource() {
extensionsService = RestClientBuilder.newBuilder()
extensionsService = QuarkusRestClientBuilder.newBuilder()
.baseUri(URI.create("https://stage.code.quarkus.io/api"))
.register(AlwaysRedirectHandler.class) <1>
.build(ExtensionsService.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import jakarta.ws.rs.ext.ContextResolver;

import org.apache.http.HttpStatus;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand All @@ -30,6 +29,7 @@
import com.fasterxml.jackson.databind.SerializationFeature;

import io.quarkus.jackson.ObjectMapperCustomizer;
import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;

Expand All @@ -45,10 +45,10 @@ public class DifferentObjectMapperForClientAndServerTest {

@BeforeEach
public void setup() {
clientUnwrappingRootElement = RestClientBuilder.newBuilder().baseUri(uri)
clientUnwrappingRootElement = QuarkusRestClientBuilder.newBuilder().baseUri(uri)
.build(MyClientUnwrappingRootElement.class);

clientNotUnwrappingRootElement = RestClientBuilder.newBuilder().baseUri(uri)
clientNotUnwrappingRootElement = QuarkusRestClientBuilder.newBuilder().baseUri(uri)
.build(MyClientNotUnwrappingRootElement.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.reactive.RestStreamElementType;
import org.jboss.resteasy.reactive.server.jackson.JacksonBasicMessageBodyReader;
Expand All @@ -24,6 +23,7 @@

import com.fasterxml.jackson.databind.ObjectMapper;

import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;
import io.smallrye.mutiny.Multi;
Expand Down Expand Up @@ -101,7 +101,7 @@ void shouldSendPayloadAndConsumeAsParametrizedType() {
@Test
void shouldRestStreamElementTypeOverwriteProducesAtClassLevel() {
var resultList = new CopyOnWriteArrayList<>();
RestClientBuilder.newBuilder().baseUri(uri)
QuarkusRestClientBuilder.newBuilder().baseUri(uri)
.build(SeeWithRestStreamElementTypeClient.class)
.getJson()
.subscribe()
Expand All @@ -113,7 +113,9 @@ void shouldRestStreamElementTypeOverwriteProducesAtClassLevel() {
}

private SseClient createClient() {
return RestClientBuilder.newBuilder().baseUri(uri).register(new JacksonBasicMessageBodyReader(new ObjectMapper()))
return QuarkusRestClientBuilder.newBuilder()
.baseUri(uri)
.register(new JacksonBasicMessageBodyReader(new ObjectMapper()))
.build(SseClient.class);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
import jakarta.ws.rs.core.MediaType;
import jakarta.xml.bind.annotation.XmlRootElement;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.rest.client.reactive.QuarkusRestClientBuilder;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;

Expand All @@ -28,14 +28,14 @@ public class SimpleJaxbTest {

@Test
void shouldConsumeXMLEntity() {
var dto = RestClientBuilder.newBuilder().baseUri(uri).build(XmlClient.class)
var dto = QuarkusRestClientBuilder.newBuilder().baseUri(uri).build(XmlClient.class)
.dto();
assertThat(dto).isEqualTo(new Dto("foo", "bar"));
}

@Test
void shouldConsumePlainXMLEntity() {
var dto = RestClientBuilder.newBuilder().baseUri(uri).build(XmlClient.class)
var dto = QuarkusRestClientBuilder.newBuilder().baseUri(uri).build(XmlClient.class)
.plain();
assertThat(dto).isEqualTo(new Dto("foo", "bar"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import jakarta.ws.rs.Path;
import jakarta.ws.rs.QueryParam;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.ext.QueryParamStyle;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
Expand Down Expand Up @@ -87,7 +86,7 @@ private void setupServer() throws InterruptedException, ExecutionException {
}

private Client createClient() {
return RestClientBuilder.newBuilder()
return QuarkusRestClientBuilder.newBuilder()
.queryParamStyle(QueryParamStyle.ARRAY_PAIRS)
.baseUri(URI.create("http://localhost:8082"))
.build(Client.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import jakarta.ws.rs.core.Response;

import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand Down Expand Up @@ -65,11 +64,10 @@ public Endpoint(ObjectMapper mapper,
@ConfigProperty(name = "quarkus.http.test-port", defaultValue = "8081") Integer testPort)
throws MalformedURLException {
this.mapper = mapper;
this.headersService = RestClientBuilder.newBuilder()
this.headersService = QuarkusRestClientBuilder.newBuilder()
.baseUrl(new URL(String.format("http://localhost:%d", testPort)))
.readTimeout(1, TimeUnit.SECONDS)
.build(HeadersService.class);
;
}

@POST
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.jboss.resteasy.reactive.client.api.QuarkusRestClientProperties;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
Expand All @@ -37,7 +36,7 @@ public class ConnectionPoolSizeTest {

@Test
void shouldPerform20CallsWithoutQueuing() throws InterruptedException {
Client client = RestClientBuilder.newBuilder().baseUri(uri)
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(uri)
.build(Client.class);

CountDownLatch latch = executeCalls(client, 20);
Expand All @@ -50,7 +49,7 @@ void shouldPerform20CallsWithoutQueuing() throws InterruptedException {
@Test
@Timeout(5)
void shouldPerform21CallsWithQueuing() throws InterruptedException {
Client client = RestClientBuilder.newBuilder().baseUri(uri)
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(uri)
.build(Client.class);

long start = System.currentTimeMillis();
Expand All @@ -63,7 +62,7 @@ void shouldPerform21CallsWithQueuing() throws InterruptedException {
@Test
@Timeout(5)
void shouldPerform5CallsWithoutQueueingOnQueue6() throws InterruptedException {
Client client = RestClientBuilder.newBuilder().baseUri(uri)
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(uri)
.property(QuarkusRestClientProperties.CONNECTION_POOL_SIZE, 6)
.build(Client.class);

Expand All @@ -77,7 +76,7 @@ void shouldPerform5CallsWithoutQueueingOnQueue6() throws InterruptedException {
@Test
@Timeout(5)
void shouldPerform5CallsWithQueueingOnQueue4() throws InterruptedException {
Client client = RestClientBuilder.newBuilder().baseUri(uri)
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(uri)
.property(QuarkusRestClientProperties.CONNECTION_POOL_SIZE, 4)
.build(Client.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import jakarta.ws.rs.Path;
import jakarta.ws.rs.ext.ContextResolver;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.jboss.resteasy.reactive.RestResponse;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand All @@ -33,12 +32,12 @@ public class CustomHttpOptionsViaProgrammaticallyClientCreatedTest {
@Test
void shouldUseCustomHttpOptions() {
// First verify the standard configuration
assertThat(RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class).get())
assertThat(QuarkusRestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class).get())
.isEqualTo(EXPECTED_VALUE);

// Now, it should fail if we use a custom http client options with a very limited max header size:

Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(baseUri)
.register(CustomHttpClientOptionsWithLimit.class)
.build(Client.class);
assertThatThrownBy(() -> client.get()).hasMessageContaining("HTTP header is larger than 1 bytes.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import jakarta.ws.rs.Path;

import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

Expand All @@ -29,7 +28,7 @@ void shouldWork() {
}

private Client clientWithUri(String uri) {
return RestClientBuilder.newBuilder().baseUri(URI.create(uri)).build(Client.class);
return QuarkusRestClientBuilder.newBuilder().baseUri(URI.create(uri)).build(Client.class);
}

@Path("/foo")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import jakarta.ws.rs.core.Form;
import jakarta.ws.rs.core.MediaType;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

Expand All @@ -29,7 +28,7 @@ public class FormTest {

@Test
void shouldPassUrlEncodedAsForm() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);
assertThat(client.echo(new Form().param("name", "World"))).isEqualTo("Hello, World!");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import jakarta.ws.rs.core.Response;

import org.assertj.core.api.Assertions;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand All @@ -22,7 +21,7 @@ public class InvalidHostTest {

@Test
void shouldThrowDummyException() {
Client client = RestClientBuilder.newBuilder().baseUri(URI.create("http://localhost2:1234/"))
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(URI.create("http://localhost2:1234/"))
.register(DummyExceptionMapper.class).build(Client.class);

Assertions.assertThatThrownBy(client::get).isInstanceOf(DummyException.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

import org.assertj.core.api.Assertions;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

Expand Down Expand Up @@ -57,7 +56,7 @@ void shouldWork() {
}

private Client clientWithUri(String uri) {
return RestClientBuilder.newBuilder().baseUri(URI.create(uri)).build(Client.class);
return QuarkusRestClientBuilder.newBuilder().baseUri(URI.create(uri)).build(Client.class);
}

@Path("/foo")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.UriInfo;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.jboss.resteasy.reactive.RestQuery;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
Expand All @@ -33,14 +32,14 @@ public class MapParamsTest {

@Test
void testQueryParamsWithRegularMap() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);
String response = client.regularMap(Map.of("foo", "bar", "k", "v"));
assertThat(response).contains("foo=bar").contains("k=v");
}

@Test
void testQueryParamsWithMultiMap() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);
MultivaluedMap<String, Integer> map = new MultivaluedHashMap<>();
map.putSingle("first", 1);
map.put("second", List.of(2, 4, 6));
Expand Down
Loading

0 comments on commit 585ebb2

Please sign in to comment.