Skip to content

Commit

Permalink
Support optional @QueryParam on Rest client
Browse files Browse the repository at this point in the history
  • Loading branch information
lasteris committed Jan 17, 2025
1 parent c45215c commit e0722b2
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 0 deletions.
4 changes: 4 additions & 0 deletions docs/src/main/asciidoc/rest-client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MultivaluedMap;
import java.util.Map;
import java.util.Set;
import java util.Optional;
@Path("/extensions")
@RegisterRestClient(configKey = "extensions-api")
Expand All @@ -168,6 +169,9 @@ public interface ExtensionsService {
@GET
Set<Extension> getByName(@RestQuery String name); <1>
@GET
Set<Extension> getByOptionalName(@RestQuery Optional<String> name);
@GET
Set<Extension> getByFilter(@RestQuery Map<String, String> filter); <2>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.MAP;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.MULTI;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.OBJECT;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.OPTIONAL;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.PART_TYPE_NAME;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.REST_FORM_PARAM;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.REST_MULTI;
Expand Down Expand Up @@ -2861,6 +2862,19 @@ private ResultHandle addQueryParam(MethodInfo jandexMethod, BytecodeCreator meth
paramArray = notNullParam.invokeStaticMethod(
MethodDescriptor.ofMethod(ToObjectArray.class, "collection", Object[].class, Collection.class),
queryParamHandle);
} else if (isOptional(type, index)) {
if (type.kind() == PARAMETERIZED_TYPE) {
Type paramType = type.asParameterizedType().arguments().get(0);
if ((paramType.kind() == CLASS) || (paramType.kind() == PARAMETERIZED_TYPE)) {
componentType = paramType.name().toString();
}
}
if (componentType == null) {
componentType = DotNames.OBJECT.toString();
}
paramArray = notNullParam.invokeStaticMethod(
MethodDescriptor.ofMethod(ToObjectArray.class, "optional", Object[].class, Optional.class),
queryParamHandle);
} else {
componentType = type.name().toString();
paramArray = notNullParam.invokeStaticMethod(
Expand Down Expand Up @@ -2930,6 +2944,10 @@ private boolean isMap(Type type, IndexView index) {
return isAssignableFrom(MAP, type.name(), index);
}

private boolean isOptional(Type type, IndexView index) {
return isAssignableFrom(OPTIONAL, type.name(), index);
}

private void addHeaderParam(BytecodeCreator invoBuilderEnricher, AssignableResultHandle invocationBuilder,
String paramName, ResultHandle headerParamHandle, String paramType, ResultHandle client,
ResultHandle genericType, ResultHandle annotations) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.quarkus.jaxrs.client.reactive.runtime;

import java.util.Collection;
import java.util.Optional;

/**
* used by query param handling mechanism, in generated code
Expand All @@ -16,6 +17,10 @@ public static Object[] value(Object value) {
return new Object[] { value };
}

public static Object[] optional(Optional<?> optional) {
return optional.isPresent() ? new Object[] { optional.get() } : new Object[] {};
}

private ToObjectArray() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package io.quarkus.rest.client.reactive;

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

import java.net.URI;
import java.util.*;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.UriInfo;

import org.jboss.resteasy.reactive.RestQuery;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.quarkus.test.common.http.TestHTTPResource;

public class OptionalQueryParamsTest {

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

@TestHTTPResource
URI baseUri;

@Test
void testQueryParamsWithOptionals() {
Client client = QuarkusRestClientBuilder.newBuilder().baseUri(baseUri).build(Client.class);
String responseForEmptyOptional = client.optional(Optional.empty());
assertThat(responseForEmptyOptional).isNull();

String responseForValueOptional = client.optional(Optional.of("value"));
assertThat(responseForValueOptional).isEqualTo("value");
}

@Path("optional")
public static class Resource {

@Path("query")
@GET
public String queryParams(@Context UriInfo uriInfo) {

if (uriInfo.getQueryParameters().isEmpty()) {
return null;
}

Map.Entry<String, List<String>> optionalParam = uriInfo.getQueryParameters().entrySet().iterator()
.next();

return optionalParam.getValue().get(0);

}
}

@Path("optional")
public interface Client {

@Path("query")
@GET
String optional(@RestQuery Optional<String> parameter);

}
}

0 comments on commit e0722b2

Please sign in to comment.