Skip to content

Commit

Permalink
Add RestClientBuilder factories
Browse files Browse the repository at this point in the history
These factories should make it easier for developers to obtain a
RestClientBuilder instance preconfigured according to current
application config. The builder can be further tweaked and then used to
programatically build a rest client proxy.
  • Loading branch information
TomasHofman committed Sep 12, 2022
1 parent 23d2600 commit c0e11c6
Show file tree
Hide file tree
Showing 12 changed files with 185 additions and 6 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package io.quarkus.restclient.config;

import java.util.ServiceLoader;

import org.eclipse.microprofile.rest.client.RestClientBuilder;

/**
* Factory which creates MicroProfile RestClientBuilder instance configured according to current Quarkus application
* configuration.
*
* The builder instance can be further tweaked, if needed, before building the rest client proxy.
*/
public interface RestClientBuilderFactory {

default RestClientBuilder newBuilder(Class<?> proxyType) {
return newBuilder(proxyType, RestClientsConfig.getInstance());
}

RestClientBuilder newBuilder(Class<?> proxyType, RestClientsConfig restClientsConfigRoot);

static RestClientBuilderFactory getInstance() {
ServiceLoader<RestClientBuilderFactory> sl = ServiceLoader.load(RestClientBuilderFactory.class);
RestClientBuilderFactory instance = null;
for (RestClientBuilderFactory spi : sl) {
if (instance != null) {
throw new IllegalStateException("Multiple RestClientBuilderFactory implementations found: "
+ spi.getClass().getName() + " and "
+ instance.getClass().getName());
}
instance = spi;
}
return instance;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package io.quarkus.restclient.configuration;

import static org.assertj.core.api.Assertions.assertThat;

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

import io.quarkus.restclient.config.RestClientBuilderFactory;
import io.quarkus.test.QuarkusUnitTest;

public class ClassicRestClientBuilderFactoryTest {

@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar.addClasses(EchoClientWithoutAnnotation.class, EchoClientWithConfigKey.class,
EchoResource.class))
.withConfigurationResource("factory-test-application.properties");

@Test
public void testAnnotatedClientClass() {
RestClientBuilder restClientBuilder = RestClientBuilderFactory.getInstance().newBuilder(EchoClientWithConfigKey.class);
EchoClientWithConfigKey restClient = restClientBuilder.build(EchoClientWithConfigKey.class);

assertThat(restClient.echo("Hello")).contains("Hello");
}

@Test
public void testNotAnnotatedClientClass() {
RestClientBuilder restClientBuilder = RestClientBuilderFactory.getInstance()
.newBuilder(EchoClientWithoutAnnotation.class);
EchoClientWithoutAnnotation restClient = restClientBuilder.build(EchoClientWithoutAnnotation.class);

assertThat(restClient.echo("Hello")).contains("Hello");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.quarkus.restclient.configuration;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;

@Path("/echo")
public interface EchoClientWithoutAnnotation {

@GET
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.TEXT_PLAIN)
String echo(@QueryParam("message") String message);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
quarkus.rest-client.echo-client.url=http://localhost:8081
quarkus.rest-client.EchoClientWithoutAnnotation.url=http://localhost:8081
quarkus.rest-client.read-timeout=3456
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.quarkus.restclient.runtime;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import io.quarkus.restclient.config.RestClientBuilderFactory;
import io.quarkus.restclient.config.RestClientsConfig;

public class ClassicRestClientBuilderFactory implements RestClientBuilderFactory {

public RestClientBuilder newBuilder(Class<?> proxyType, RestClientsConfig restClientsConfigRoot) {
RegisterRestClient annotation = proxyType.getAnnotation(RegisterRestClient.class);
String configKey = null;
String baseUri = null;
if (annotation != null) {
configKey = annotation.configKey();
baseUri = annotation.baseUri();
}

RestClientBuilder restClientBuilder = RestClientBuilder.newBuilder();
RestClientBase restClientBase = new RestClientBase(proxyType, baseUri, configKey, new Class[0], restClientsConfigRoot);
restClientBase.configureBuilder(restClientBuilder);

return restClientBuilder;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.restclient.runtime.ClassicRestClientBuilderFactory
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.quarkus.rest.client.reactive;

import static org.assertj.core.api.Assertions.assertThat;

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.configuration.EchoResource;
import io.quarkus.restclient.config.RestClientBuilderFactory;
import io.quarkus.test.QuarkusUnitTest;

public class ReactiveRestClientBuilderFactoryTest {

@RegisterExtension
static final QuarkusUnitTest TEST = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar.addClasses(HelloClient2.class, EchoResource.class))
.withConfigurationResource("factory-test-application.properties");

@Test
public void test() throws Exception {
RestClientBuilder restClientBuilder = RestClientBuilderFactory.getInstance().newBuilder(HelloClient2.class);
HelloClient2 restClient = restClientBuilder.build(HelloClient2.class);

assertThat(restClientBuilder.getConfiguration().getProperties().get("io.quarkus.rest.client.read-timeout"))
.isEqualTo(3456L);
assertThat(restClient.echo("Hello")).contains("Hello");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
quarkus.rest-client.hello2.url=http://localhost:8081/hello
quarkus.rest-client.read-timeout=3456
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.rest.client.reactive.runtime;

import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;

import io.quarkus.restclient.config.RestClientBuilderFactory;
import io.quarkus.restclient.config.RestClientsConfig;

public class ReactiveRestClientBuilderFactory implements RestClientBuilderFactory {

public RestClientBuilder newBuilder(Class<?> proxyType, RestClientsConfig restClientsConfigRoot) {
RegisterRestClient annotation = proxyType.getAnnotation(RegisterRestClient.class);
String configKey = null;
String baseUri = null;
if (annotation != null) {
configKey = annotation.configKey();
baseUri = annotation.baseUri();
}

RestClientBuilderImpl restClientBuilder = new RestClientBuilderImpl();
RestClientCDIDelegateBuilder<?> restClientBase = new RestClientCDIDelegateBuilder<>(proxyType, baseUri, configKey,
restClientsConfigRoot);
restClientBase.configureBuilder(restClientBuilder);

return restClientBuilder;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,11 @@ private T build() {
throw new IllegalStateException("Expected RestClientBuilder to be an instance of "
+ RestClientBuilderImpl.class.getName() + ", got " + builder.getClass().getName());
}
return build((RestClientBuilderImpl) builder);
configureBuilder((RestClientBuilderImpl) builder);
return builder.build(jaxrsInterface);
}

T build(RestClientBuilderImpl builder) {
void configureBuilder(RestClientBuilderImpl builder) {
configureBaseUrl(builder);
configureTimeouts(builder);
configureProviders(builder);
Expand All @@ -73,12 +74,11 @@ T build(RestClientBuilderImpl builder) {
configureProxy(builder);
configureShared(builder);
configureCustomProperties(builder);
return builder.build(jaxrsInterface);
}

private void configureCustomProperties(RestClientBuilder builder) {
Optional<String> encoder = configRoot.multipartPostEncoderMode;
if (encoder.isPresent()) {
if (encoder != null && encoder.isPresent()) {
HttpPostRequestEncoder.EncoderMode mode = HttpPostRequestEncoder.EncoderMode
.valueOf(encoder.get().toUpperCase(Locale.ROOT));
builder.property(QuarkusRestClientProperties.MULTIPART_ENCODER_MODE, mode);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
io.quarkus.rest.client.reactive.runtime.ReactiveRestClientBuilderFactory
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public void testClientSpecificConfigs() {
new RestClientCDIDelegateBuilder<>(TestClient.class,
"http://localhost:8080",
"test-client",
configRoot).build(restClientBuilderMock);
configRoot).configureBuilder(restClientBuilderMock);

// then

Expand Down Expand Up @@ -125,7 +125,7 @@ public void testGlobalConfigs() {
new RestClientCDIDelegateBuilder<>(TestClient.class,
"http://localhost:8080",
"test-client",
configRoot).build(restClientBuilderMock);
configRoot).configureBuilder(restClientBuilderMock);

// then

Expand Down

0 comments on commit c0e11c6

Please sign in to comment.