Skip to content

Commit

Permalink
programmatic client generation for MP Rest Client, fixes #1317
Browse files Browse the repository at this point in the history
  • Loading branch information
michalszynkiewicz authored and gsmet committed Mar 15, 2019
1 parent 2ee62e5 commit cf151ac
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 12 deletions.
7 changes: 6 additions & 1 deletion docs/src/main/asciidoc/rest-client-guide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,8 @@ The `getByName` method gives our code the ability to query a country by name fro

The purpose of the annotations in the code above is the following:

* `@RegisterRestClient` allows {project-name} to know that this interface is meant to be used as a REST Client
* `@RegisterRestClient` allows {project-name} to know that this interface is meant to be available for
CDI injection as a REST Client
* `@Path`, `@GET` and `@PathParam` are the standard JAX-RS annotations used to define how to access the service
* `@Produces` defines the expected content-type

Expand Down Expand Up @@ -268,3 +269,7 @@ You should see a JSON object containing some basic information about Greece.

As usual, the application can be packaged using `mvn clean package` and executed using the `-runner.jar` file.
You can also generate the native executable with `mvn clean package -Pnative`.

== Further reading

* link:https://download.eclipse.org/microprofile/microprofile-rest-client-1.2.1/microprofile-rest-client-1.2.1.html[MicroProfile Rest Client specification]
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,19 @@
import java.util.Map;
import java.util.Set;

import javax.ws.rs.Path;
import javax.ws.rs.client.ClientRequestFilter;
import javax.ws.rs.client.ClientResponseFilter;
import javax.ws.rs.ext.Providers;

import org.apache.commons.logging.impl.Jdk14Logger;
import org.apache.commons.logging.impl.LogFactoryImpl;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.IndexView;
import org.jboss.jandex.MethodInfo;
import org.jboss.jandex.Type;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
Expand All @@ -47,7 +48,6 @@
import io.quarkus.arc.processor.BeanConfigurator;
import io.quarkus.arc.processor.BeanRegistrar;
import io.quarkus.arc.processor.BuiltinScope;
import io.quarkus.arc.processor.ScopeInfo;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.annotations.ExecutionTime;
Expand All @@ -73,7 +73,7 @@ class SmallRyeRestClientProcessor {

private static final DotName REST_CLIENT = DotName.createSimple(RestClient.class.getName());

private static final DotName REGISTER_REST_CLIENT = DotName.createSimple(RegisterRestClient.class.getName());
private static final DotName PATH = DotName.createSimple(Path.class.getName());

private static final String PROVIDERS_SERVICE_FILE = "META-INF/services/" + Providers.class.getName();

Expand Down Expand Up @@ -141,7 +141,8 @@ void processInterfaces(CombinedIndexBuildItem combinedIndexBuildItem,
Map<DotName, ClassInfo> interfaces = new HashMap<>();
Set<Type> returnTypes = new HashSet<>();

for (AnnotationInstance annotation : combinedIndexBuildItem.getIndex().getAnnotations(REGISTER_REST_CLIENT)) {
IndexView index = combinedIndexBuildItem.getIndex();
for (AnnotationInstance annotation : index.getAnnotations(PATH)) {
AnnotationTarget target = annotation.target();
ClassInfo theInfo;
if (target.kind() == AnnotationTarget.Kind.CLASS) {
Expand All @@ -151,9 +152,11 @@ void processInterfaces(CombinedIndexBuildItem combinedIndexBuildItem,
} else {
continue;
}
if (!Modifier.isInterface(theInfo.flags())) {

if (!isRestClientInterface(index, theInfo)) {
continue;
}

interfaces.put(theInfo.name(), theInfo);

// Find Return types
Expand Down Expand Up @@ -212,4 +215,9 @@ public void register(RegistrationContext registrationContext) {
extensionSslNativeSupport.produce(new ExtensionSslNativeSupportBuildItem(FeatureBuildItem.SMALLRYE_REST_CLIENT));
RestClientBuilderImpl.SSL_ENABLED = sslNativeConfig.isEnabled();
}

private boolean isRestClientInterface(IndexView index, ClassInfo classInfo) {
return Modifier.isInterface(classInfo.flags())
&& index.getAllKnownImplementors(classInfo.name()).isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ public class ClientResource {
@GET
@Path("/manual")
public String manual() throws Exception {
RestInterface iface = RestClientBuilder.newBuilder()
ProgrammaticRestInterface iface = RestClientBuilder.newBuilder()
.baseUrl(new URL(System.getProperty("test.url")))
.build(RestInterface.class);
.build(ProgrammaticRestInterface.class);
return iface.get();
}

Expand All @@ -53,9 +53,9 @@ public String cdi() throws Exception {
@Path("manual/jackson")
@Produces("application/json")
public TestResource.MyData getDataManual() throws Exception {
RestInterface iface = RestClientBuilder.newBuilder()
ProgrammaticRestInterface iface = RestClientBuilder.newBuilder()
.baseUrl(new URL(System.getProperty("test.url")))
.build(RestInterface.class);
.build(ProgrammaticRestInterface.class);
System.out.println(iface.getData());
return iface.getData();
}
Expand All @@ -71,9 +71,9 @@ public TestResource.MyData getDataCdi() {
@Path("/manual/complex")
@Produces("application/json")
public List<ComponentType> complexManual() throws Exception {
RestInterface iface = RestClientBuilder.newBuilder()
ProgrammaticRestInterface iface = RestClientBuilder.newBuilder()
.baseUrl(new URL(System.getProperty("test.url")))
.build(RestInterface.class);
.build(ProgrammaticRestInterface.class);
System.out.println(iface.complex());
return iface.complex();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.example.rest;

import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

/**
* A version of {@link RestInterface} that doesn't have {@link org.eclipse.microprofile.rest.client.inject.RegisterRestClient}
* and can be used only programmatically, i.e. with the builder.
*/
@Path("/test")
public interface ProgrammaticRestInterface {

@GET
String get();

@GET
@Path("/jackson")
@Produces("application/json")
TestResource.MyData getData();

@GET
@Path("/complex")
@Produces("application/json")
List<ComponentType> complex();
}

0 comments on commit cf151ac

Please sign in to comment.