Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add @ClientFormParam to Reactive REST Client #34535

Merged
merged 1 commit into from
Jul 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 82 additions & 7 deletions docs/src/main/asciidoc/rest-client-reactive.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,82 @@ Note that if an interface method contains an argument annotated with `@QueryPara
priority over anything specified in any `@ClientQueryParam` annotation.
====

More information about this annotation can be found on the javadoc of
More information about this annotation can be found on the javadoc of link:https://javadoc.io/doc/io.quarkus/quarkus-rest-client-reactive/latest/io/quarkus/rest/client/reactive/ClientQueryParam.html[`@ClientQueryParam`].

=== Form Parameters

Form parameters can be specified using `@RestForm` (or `@FormParam`) annotations:

[source, java]
----
package org.acme.rest.client;

import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
import org.jboss.resteasy.reactive.RestForm;

import jakarta.ws.rs.PORT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.FormParam;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.Map;
import java.util.Set;

@Path("/extensions")
@RegisterRestClient(configKey = "extensions-api")
public interface ExtensionsService {

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
Set<Extension> postId(@FormParam("id") Integer id);

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
Set<Extension> postName(@RestForm String name);

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
Set<Extension> postFilter(@RestForm Map<String, String> filter);

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
Set<Extension> postFilters(@RestForm MultivaluedMap<String, String> filters);

}
----

==== Using @ClientFormParam

Form parameters can also be specified using `@ClientFormParam`, similar to `@ClientQueryParam`:

[source, java]
----
@ClientFormParam(name = "my-param", value = "${my.property-value}")
public interface Client {
@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
String postWithParam();

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@ClientFormParam(name = "some-other-param", value = "other")
String postWithOtherParam();

@POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@ClientFormParam(name = "param-from-method", value = "{with-param}")
String postFromMethod();

default String withParam(String name) {
if ("param-from-method".equals(name)) {
return "test";
}
throw new IllegalArgumentException();
}
}
----

More information about this annotation can be found on the javadoc of link:https://javadoc.io/doc/io.quarkus/quarkus-rest-client-reactive/latest/io/quarkus/rest/client/reactive/ClientFormParam.html[`@ClientFormParam`].

=== Path Parameters

Expand Down Expand Up @@ -520,7 +595,7 @@ A HTTP server can redirect a response to another location by sending a response
- `quarkus.rest-client.follow-redirects` to enable redirection for all REST clients.
- `quarkus.rest-client.<client-prefix>.follow-redirects` to enable redirection for a specific REST client.

If this property is true, then REST Client will perform a new request that it receives a redirection response from the HTTP server.
If this property is true, then REST Client will perform a new request that it receives a redirection response from the HTTP server.

Additionally, we can limit the number of redirections using the property "max-redirects".

Expand Down Expand Up @@ -994,7 +1069,7 @@ QuarkusRestClientBuilder.newBuilder()

=== Injecting the `jakarta.ws.rs.ext.Providers` instance in filters

The `jakarta.ws.rs.ext.Providers` is useful when we need to lookup the provider instances of the current client.
The `jakarta.ws.rs.ext.Providers` is useful when we need to lookup the provider instances of the current client.

We can get the `Providers` instance in our filters from the request context as follows:

Expand Down Expand Up @@ -1086,7 +1161,7 @@ NOTE: Methods annotated with `@ClientExceptionMapper` can also take a `java.lang

=== Using @Blocking annotation in exception mappers

In cases that warrant using `InputStream` as the return type of REST Client method (such as when large amounts of data need to be read):
In cases that warrant using `InputStream` as the return type of REST Client method (such as when large amounts of data need to be read):

[source, java]
----
Expand Down Expand Up @@ -1120,8 +1195,8 @@ public class MyResponseExceptionMapper implements ResponseExceptionMapper<Runtim
}
----

<1> With the `@Blocking` annotation, the MyResponseExceptionMapper exception mapper will be executed in the worker thread pool.
<2> Reading the entity is now allowed because we're executing the mapper on the worker thread pool.
<1> With the `@Blocking` annotation, the MyResponseExceptionMapper exception mapper will be executed in the worker thread pool.
<2> Reading the entity is now allowed because we're executing the mapper on the worker thread pool.

Note that you can also use the `@Blocking` annotation when using @ClientExceptionMapper:

Expand Down Expand Up @@ -1288,7 +1363,7 @@ As previously mentioned, the body parameter needs to be properly crafted by the

=== Receiving compressed messages
REST Client Reactive also supports receiving compressed messages using GZIP. You can enable the HTTP compression support by adding the property `quarkus.http.enable-compression=true`.
When this feature is enabled and a server returns a response that includes the header `Content-Encoding: gzip`, REST Client Reactive will automatically decode the content and proceed with the message handling.
When this feature is enabled and a server returns a response that includes the header `Content-Encoding: gzip`, REST Client Reactive will automatically decode the content and proceed with the message handling.

== Proxy support
REST Client Reactive supports sending requests through a proxy.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,15 @@ void forSubResourceWebTarget(MethodCreator methodCreator, IndexView index, Class
MethodInfo rootMethod, MethodInfo subMethod, AssignableResultHandle webTarget,
BuildProducer<GeneratedClassBuildItem> generatedClasses);

AssignableResultHandle handleFormParams(MethodCreator methodCreator, IndexView index, ClassInfo interfaceClass,
MethodInfo method, BuildProducer<GeneratedClassBuildItem> generatedClasses,
AssignableResultHandle formParams, boolean multipart);

AssignableResultHandle handleFormParamsForSubResource(MethodCreator methodCreator, IndexView index,
ClassInfo rootInterfaceClass, ClassInfo subInterfaceClass, MethodInfo rootMethod, MethodInfo subMethod,
AssignableResultHandle webTarget, BuildProducer<GeneratedClassBuildItem> generatedClasses,
AssignableResultHandle formParams, boolean multipart);

/**
* Method-level alterations
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,8 @@ A more full example of generated client (with sub-resource) can is at the bottom
enricher.getEnricher()
.forWebTarget(methodCreator, index, interfaceClass, jandexMethod, methodTarget,
generatedClasses);
formParams = enricher.getEnricher().handleFormParams(methodCreator, index, interfaceClass, jandexMethod,
generatedClasses, formParams, multipart);
}

AssignableResultHandle builder = methodCreator.createVariable(Invocation.Builder.class);
Expand Down Expand Up @@ -1660,6 +1662,9 @@ private void handleSubResourceMethod(List<JaxrsClientReactiveEnricherBuildItem>
enricher.getEnricher()
.forSubResourceWebTarget(subMethodCreator, index, interfaceClass, subInterface,
jandexMethod, jandexSubMethod, methodTarget, generatedClasses);
formParams = enricher.getEnricher().handleFormParamsForSubResource(subMethodCreator, index,
interfaceClass, subInterface, jandexMethod, jandexSubMethod, methodTarget, generatedClasses,
formParams, multipart);
}

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
Loading