Skip to content

Commit

Permalink
Add @ClientFormParam to Reactive REST Client
Browse files Browse the repository at this point in the history
  • Loading branch information
Eng-Fouad committed Jul 5, 2023
1 parent ac5b8d0 commit 06800ad
Show file tree
Hide file tree
Showing 11 changed files with 630 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@ void forClass(MethodCreator ctor, AssignableResultHandle globalTarget,
* Called when a {@link jakarta.ws.rs.client.WebTarget} has been populated for a normal Client
*/
void forWebTarget(MethodCreator methodCreator, IndexView index, ClassInfo interfaceClass, MethodInfo method,
AssignableResultHandle webTarget, BuildProducer<GeneratedClassBuildItem> generatedClasses);
AssignableResultHandle webTarget, BuildProducer<GeneratedClassBuildItem> generatedClasses,
AssignableResultHandle formValues);

/**
* Called when a {@link jakarta.ws.rs.client.WebTarget} has been populated for a sub Client
*/
void forSubResourceWebTarget(MethodCreator methodCreator, IndexView index, ClassInfo rootInterfaceClass,
ClassInfo subInterfaceClass,
MethodInfo rootMethod, MethodInfo subMethod, AssignableResultHandle webTarget,
BuildProducer<GeneratedClassBuildItem> generatedClasses);
BuildProducer<GeneratedClassBuildItem> generatedClasses, AssignableResultHandle formValues);

/**
* Method-level alterations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1036,7 +1036,7 @@ A more full example of generated client (with sub-resource) can is at the bottom
for (JaxrsClientReactiveEnricherBuildItem enricher : enrichers) {
enricher.getEnricher()
.forWebTarget(methodCreator, index, interfaceClass, jandexMethod, methodTarget,
generatedClasses);
generatedClasses, formParams);
}

AssignableResultHandle builder = methodCreator.createVariable(Invocation.Builder.class);
Expand Down Expand Up @@ -1659,7 +1659,7 @@ private void handleSubResourceMethod(List<JaxrsClientReactiveEnricherBuildItem>
for (JaxrsClientReactiveEnricherBuildItem enricher : enrichers) {
enricher.getEnricher()
.forSubResourceWebTarget(subMethodCreator, index, interfaceClass, subInterface,
jandexMethod, jandexSubMethod, methodTarget, generatedClasses);
jandexMethod, jandexSubMethod, methodTarget, generatedClasses, formParams);
}

AssignableResultHandle builder = subMethodCreator.createVariable(Invocation.Builder.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import org.jboss.jandex.DotName;

import io.quarkus.rest.client.reactive.ClientExceptionMapper;
import io.quarkus.rest.client.reactive.ClientFormParam;
import io.quarkus.rest.client.reactive.ClientFormParams;
import io.quarkus.rest.client.reactive.ClientQueryParam;
import io.quarkus.rest.client.reactive.ClientQueryParams;
import io.quarkus.rest.client.reactive.ClientRedirectHandler;
Expand All @@ -27,6 +29,8 @@ public class DotNames {

public static final DotName CLIENT_QUERY_PARAM = DotName.createSimple(ClientQueryParam.class.getName());
public static final DotName CLIENT_QUERY_PARAMS = DotName.createSimple(ClientQueryParams.class.getName());
public static final DotName CLIENT_FORM_PARAM = DotName.createSimple(ClientFormParam.class.getName());
public static final DotName CLIENT_FORM_PARAMS = DotName.createSimple(ClientFormParams.class.getName());
public static final DotName REGISTER_CLIENT_HEADERS = DotName.createSimple(RegisterClientHeaders.class.getName());
public static final DotName CLIENT_REQUEST_FILTER = DotName.createSimple(ClientRequestFilter.class.getName());
public static final DotName CLIENT_RESPONSE_FILTER = DotName.createSimple(ClientResponseFilter.class.getName());
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static io.quarkus.arc.processor.MethodDescriptors.MAP_PUT;
import static io.quarkus.rest.client.reactive.deployment.DotNames.CLIENT_EXCEPTION_MAPPER;
import static io.quarkus.rest.client.reactive.deployment.DotNames.CLIENT_FORM_PARAM;
import static io.quarkus.rest.client.reactive.deployment.DotNames.CLIENT_FORM_PARAMS;
import static io.quarkus.rest.client.reactive.deployment.DotNames.CLIENT_HEADER_PARAM;
import static io.quarkus.rest.client.reactive.deployment.DotNames.CLIENT_HEADER_PARAMS;
import static io.quarkus.rest.client.reactive.deployment.DotNames.CLIENT_QUERY_PARAM;
Expand All @@ -12,7 +14,7 @@
import static io.quarkus.rest.client.reactive.deployment.DotNames.REGISTER_PROVIDERS;
import static io.quarkus.rest.client.reactive.deployment.DotNames.RESPONSE_EXCEPTION_MAPPER;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.*;
import static java.util.stream.Collectors.toList;
import static org.jboss.resteasy.reactive.common.processor.EndpointIndexer.CDI_WRAPPER_SUFFIX;
import static org.jboss.resteasy.reactive.common.processor.JandexUtil.isImplementorOf;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.BLOCKING;
Expand Down Expand Up @@ -121,6 +123,8 @@ class RestClientReactiveProcessor {
CLIENT_HEADER_PARAMS,
CLIENT_QUERY_PARAM,
CLIENT_QUERY_PARAMS,
CLIENT_FORM_PARAM,
CLIENT_FORM_PARAMS,
REGISTER_CLIENT_HEADERS);

@BuildStep
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package io.quarkus.rest.client.reactive.form;

import io.quarkus.rest.client.reactive.ClientFormParam;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.*;
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;

import java.net.URI;
import java.util.List;

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

public class ClientFormParamFromMethodTest {

@TestHTTPResource
URI baseUri;

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar.addClasses(Client.class, SubClient.class, Resource.class, ComputedParam.class));

@Test
void shouldUseValuesOnlyFromClass() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.setFromClass()).isEqualTo("1/");
}

@Test
void shouldUseValuesFromClassAndMethod() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.setFromMethodAndClass()).isEqualTo("1/2");
}

@Test
void shouldUseValuesFromMethodWithParam() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.setFromMethodWithParam()).isEqualTo("-11/-2");
}

@Test
void shouldUseValuesFromFormParam() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.setFromFormParam("111")).isEqualTo("111/2");
}

@Test
void shouldUseValuesFromFormParams() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.setFromFormParams("111", "222")).isEqualTo("111/222");
}

@Test
void shouldUseValuesFromSubclientAnnotations() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.sub().sub("22")).isEqualTo("11/22");
}

@Path("/")
@ApplicationScoped
public static class Resource {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
public String returnFormParamValues(@FormParam("first") List<String> first,
@FormParam("second") List<String> second) {
return String.join(",", first) + "/" + String.join(",", second);
}
}

@ClientFormParam(name = "first", value = "{first}")
public interface Client {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
String setFromClass();

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
@ClientFormParam(name = "second", value = "{second}")
String setFromMethodAndClass();

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
@ClientFormParam(name = "second", value = "{second}")
String setFromFormParam(@FormParam("first") String first);

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
@ClientFormParam(name = "second", value = "{second}")
String setFromFormParams(@FormParam("first") String first, @FormParam("second") String second);

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
@ClientFormParam(name = "first", value = "{io.quarkus.rest.client.reactive.form.ComputedParam.withParam}")
@ClientFormParam(name = "second", value = "{withParam}")
String setFromMethodWithParam();

@Path("")
SubClient sub();

default String first() {
return "1";
}

default String second() {
return "2";
}

default String withParam(String name) {
if ("first".equals(name)) {
return "-1";
} else if ("second".equals(name)) {
return "-2";
}
throw new IllegalArgumentException();
}
}

@ClientFormParam(name = "first", value = "{first}")
public interface SubClient {

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
String sub(@FormParam("second") String second);

default String first() {
return "11";
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package io.quarkus.rest.client.reactive.form;

import io.quarkus.rest.client.reactive.ClientFormParam;
import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import org.jboss.shrinkwrap.api.asset.StringAsset;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import java.net.URI;

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

public class ClientFormParamFromPropertyTest {
private static final String FORM_VALUE = "foo";

@TestHTTPResource
URI baseUri;

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar.addClasses(Client.class, Resource.class)
.addAsResource(
new StringAsset("my.property-value=" + FORM_VALUE),
"application.properties"));

@Test
void shouldSetFromProperties() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.getWithParam()).isEqualTo(FORM_VALUE);
}

@Test
void shouldFailOnMissingRequiredProperty() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThatThrownBy(client::missingRequiredProperty)
.isInstanceOf(IllegalArgumentException.class);
}

@Test
void shouldSucceedOnMissingNonRequiredProperty() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.missingNonRequiredProperty()).isEqualTo(FORM_VALUE);
}

@Test
void shouldSucceedOnMissingNonRequiredPropertyAndUseOverriddenValue() {
Client client = RestClientBuilder.newBuilder().baseUri(baseUri)
.build(Client.class);

assertThat(client.missingNonRequiredPropertyAndOverriddenValue()).isEqualTo("other");
}

@Path("/")
@ApplicationScoped
public static class Resource {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
public String returnFormParamValue(@FormParam("my-param") String param) {
return param;
}
}

@ClientFormParam(name = "my-param", value = "${my.property-value}")
public interface Client {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
String getWithParam();

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
@ClientFormParam(name = "some-other-param", value = "${non-existent-property}")
String missingRequiredProperty();

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
@ClientFormParam(name = "some-other-param", value = "${non-existent-property}", required = false)
String missingNonRequiredProperty();

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.TEXT_PLAIN)
@ClientFormParam(name = "some-other-param", value = "${non-existent-property}", required = false)
@ClientFormParam(name = "my-param", value = "other")
String missingNonRequiredPropertyAndOverriddenValue();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package io.quarkus.rest.client.reactive.form;

public class ComputedParam {

public static String withParam(String name) {
if ("first".equals(name)) {
return "-11";
} else if ("second".equals(name)) {
return "-22";
}
throw new IllegalArgumentException();
}
}
Loading

0 comments on commit 06800ad

Please sign in to comment.