Skip to content

Commit

Permalink
Merge pull request #14792 from geoand/rr-optional-params
Browse files Browse the repository at this point in the history
Add Optional parameter support in RESTEasy Reactive
  • Loading branch information
geoand authored Feb 4, 2021
2 parents 2fce745 + d0702bc commit 4e6a669
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ protected MethodParameter createMethodParameter(ClassInfo currentClassInfo, Clas
String elementType, boolean single, String signature) {
return new MethodParameter(name,
elementType, toClassName(paramType, currentClassInfo, actualEndpointInfo, index), signature, type, single,
defaultValue, parameterResult.isObtainedAsCollection(), encoded);
defaultValue, parameterResult.isObtainedAsCollection(), parameterResult.isOptional(), encoded);
}

protected void addWriterForType(AdditionalWriters additionalWriters, Type paramType) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.quarkus.resteasy.reactive.server.test.simple;

import java.util.Optional;

import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
Expand Down Expand Up @@ -42,11 +44,14 @@ public String get(String klass, String regex, String id) {
@Path("params/{p}")
public String params(@RestPath String p,
@RestQuery String q,
@RestQuery Optional<String> q2,
@RestQuery Optional<Integer> q3,
@RestHeader int h,
@RestForm String f,
@RestMatrix String m,
@RestCookie String c) {
return "params: p: " + p + ", q: " + q + ", h: " + h + ", f: " + f + ", m: " + m + ", c: " + c;
return "params: p: " + p + ", q: " + q + ", h: " + h + ", f: " + f + ", m: " + m + ", c: " + c + ", q2: "
+ q2.orElse("empty") + ", q3: " + q3.orElse(-1);
}

@GET
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -379,12 +379,13 @@ public void testNewParams() {
.urlEncodingEnabled(false)
.cookie("c", "cv")
.queryParam("q", "qv")
.queryParam("q3", "999")
.header("h", "123")
.formParam("f", "fv")
.post("/new-params/myklass;m=mv/myregex/params/pv")
.then()
.log().ifError()
.body(Matchers.equalTo("params: p: pv, q: qv, h: 123, f: fv, m: mv, c: cv"));
.body(Matchers.equalTo("params: p: pv, q: qv, h: 123, f: fv, m: mv, c: cv, q2: empty, q3: 999"));
RestAssured.get("/new-params/myklass/myregex/sse")
.then()
.log().ifError()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.MATRIX_PARAM;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.MULTI;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.NON_BLOCKING;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.OPTIONAL;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.PATH;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.PATH_PARAM;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.PATH_SEGMENT;
Expand Down Expand Up @@ -832,6 +833,13 @@ && isContextType(paramType.asClassType())) {
if (convertible) {
handleSortedSetParam(existingConverters, errorLocation, hasRuntimeConverters, builder, elementType);
}
} else if (pt.name().equals(OPTIONAL)) {
typeHandled = true;
elementType = toClassName(pt.arguments().get(0), currentClassInfo, actualEndpointInfo, index);
if (convertible) {
handleOptionalParam(existingConverters, errorLocation, hasRuntimeConverters, builder, elementType);
}
builder.setOptional(true);
} else if (convertible) {
throw new RuntimeException("Invalid parameter type '" + pt + "' used on method " + errorLocation);
}
Expand Down Expand Up @@ -876,6 +884,10 @@ protected void handleSortedSetParam(Map<String, String> existingConverters, Stri
boolean hasRuntimeConverters, PARAM builder, String elementType) {
}

protected void handleOptionalParam(Map<String, String> existingConverters, String errorLocation,
boolean hasRuntimeConverters, PARAM builder, String elementType) {
}

protected void handleSetParam(Map<String, String> existingConverters, String errorLocation, boolean hasRuntimeConverters,
PARAM builder, String elementType) {
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public class IndexedParameter<T extends IndexedParameter<T>> {
protected ParameterType type;
protected String elementType;
protected boolean single;
protected boolean optional;

public boolean isObtainedAsCollection() {
return !single
Expand Down Expand Up @@ -198,4 +199,12 @@ public T setSingle(boolean single) {
return (T) this;
}

public boolean isOptional() {
return optional;
}

public T setOptional(boolean optional) {
this.optional = optional;
return (T) this;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@ public class MethodParameter {
public boolean encoded;
private boolean single;
private String defaultValue;
private boolean optional;
private boolean isObtainedAsCollection;

public MethodParameter() {
}

public MethodParameter(String name, String type, String declaredType, String signature, ParameterType parameterType,
boolean single,
String defaultValue, boolean isObtainedAsCollection, boolean encoded) {
String defaultValue, boolean isObtainedAsCollection, boolean optional, boolean encoded) {
this.name = name;
this.type = type;
this.declaredType = declaredType;
Expand All @@ -30,6 +31,7 @@ public MethodParameter(String name, String type, String declaredType, String sig
this.single = single;
this.defaultValue = defaultValue;
this.isObtainedAsCollection = isObtainedAsCollection;
this.optional = optional;
this.encoded = encoded;
}

Expand Down Expand Up @@ -88,6 +90,14 @@ public boolean isObtainedAsCollection() {
return isObtainedAsCollection;
}

public boolean isOptional() {
return optional;
}

public void setOptional(boolean optional) {
this.optional = optional;
}

public MethodParameter setObtainedAsCollection(boolean isObtainedAsCollection) {
this.isObtainedAsCollection = isObtainedAsCollection;
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames;
import org.jboss.resteasy.reactive.server.core.parameters.ParameterExtractor;
import org.jboss.resteasy.reactive.server.core.parameters.converters.ListConverter;
import org.jboss.resteasy.reactive.server.core.parameters.converters.OptionalConverter;
import org.jboss.resteasy.reactive.server.core.parameters.converters.ParameterConverterSupplier;
import org.jboss.resteasy.reactive.server.core.parameters.converters.PathSegmentParamConverter;
import org.jboss.resteasy.reactive.server.core.parameters.converters.SetConverter;
Expand Down Expand Up @@ -230,7 +231,7 @@ protected MethodParameter createMethodParameter(ClassInfo currentClassInfo, Clas
return new ServerMethodParameter(name,
elementType, toClassName(paramType, currentClassInfo, actualEndpointInfo, index),
type, single, signature,
converter, defaultValue, parameterResult.isObtainedAsCollection(), encoded,
converter, defaultValue, parameterResult.isObtainedAsCollection(), parameterResult.isOptional(), encoded,
parameterResult.getCustomerParameterExtractor());
}

Expand All @@ -247,6 +248,13 @@ protected void handleSortedSetParam(Map<String, String> existingConverters, Stri
builder.setConverter(new SortedSetConverter.SortedSetSupplier(converter));
}

protected void handleOptionalParam(Map<String, String> existingConverters, String errorLocation,
boolean hasRuntimeConverters, ServerIndexedParameter builder, String elementType) {
ParameterConverterSupplier converter = extractConverter(elementType, index,
existingConverters, errorLocation, hasRuntimeConverters);
builder.setConverter(new OptionalConverter.OptionalSupplier(converter));
}

protected void handleSetParam(Map<String, String> existingConverters, String errorLocation, boolean hasRuntimeConverters,
ServerIndexedParameter builder, String elementType) {
ParameterConverterSupplier converter = extractConverter(elementType, index,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package org.jboss.resteasy.reactive.server.core.parameters.converters;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Optional;
import org.jboss.resteasy.reactive.server.model.ParamConverterProviders;

public class OptionalConverter implements ParameterConverter {

private final ParameterConverter delegate;

public OptionalConverter(ParameterConverter delegate) {
this.delegate = delegate;
}

@Override
public Object convert(Object parameter) {
if (parameter == null) {
return Optional.empty();
} else if (delegate != null) {
return Optional.ofNullable(delegate.convert(parameter));
} else {
return Optional.of(parameter);
}
}

@Override
public void init(ParamConverterProviders deployment, Class<?> rawType, Type genericType, Annotation[] annotations) {
delegate.init(deployment, rawType, genericType, annotations);
}

public static class OptionalSupplier implements DelegatingParameterConverterSupplier {
private ParameterConverterSupplier delegate;

public OptionalSupplier() {
}

public OptionalSupplier(ParameterConverterSupplier delegate) {
this.delegate = delegate;
}

@Override
public ParameterConverter get() {
return delegate == null ? new OptionalConverter(null) : new OptionalConverter(delegate.get());
}

public ParameterConverterSupplier getDelegate() {
return delegate;
}

public OptionalSupplier setDelegate(ParameterConverterSupplier delegate) {
this.delegate = delegate;
return this;
}

@Override
public String getClassName() {
return OptionalConverter.class.getName();
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ public RuntimeResource buildResourceMethod(ResourceClass clazz,

handlers.add(new ParameterHandler(i, param.getDefaultValue(), extractor,
converter, param.parameterType,
param.isObtainedAsCollection()));
param.isObtainedAsCollection(), param.isOptional()));
}
addHandlers(handlers, method, info, HandlerChainCustomizer.Phase.BEFORE_METHOD_INVOKE);
handlers.add(new InvocationHandler(invoker));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,17 @@ public class ParameterHandler implements ServerRestHandler {
private final ParameterConverter converter;
private final ParameterType parameterType;
private final boolean isCollection;
private final boolean isOptional;

public ParameterHandler(int index, String defaultValue, ParameterExtractor extractor, ParameterConverter converter,
ParameterType parameterType, boolean isCollection) {
ParameterType parameterType, boolean isCollection, boolean isOptional) {
this.index = index;
this.defaultValue = defaultValue;
this.extractor = extractor;
this.converter = converter;
this.parameterType = parameterType;
this.isCollection = isCollection;
this.isOptional = isOptional;
}

@Override
Expand Down Expand Up @@ -65,7 +67,7 @@ private void handleResult(Object result, ResteasyReactiveRequestContext requestC
result = defaultValue;
}
Throwable toThrow = null;
if (converter != null && result != null) {
if (converter != null && ((result != null) || isOptional)) {
// spec says:
/*
* 3.2 Fields and Bean Properties
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ public ServerMethodParameter() {

public ServerMethodParameter(String name, String type, String declaredType, ParameterType parameterType, boolean single,
String signature,
ParameterConverterSupplier converter, String defaultValue, boolean isObtainedAsCollection, boolean encoded,
ParameterConverterSupplier converter, String defaultValue, boolean isObtainedAsCollection, boolean isOptional,
boolean encoded,
ParameterExtractor customerParameterExtractor) {
super(name, type, declaredType, signature, parameterType, single, defaultValue, isObtainedAsCollection, encoded);
super(name, type, declaredType, signature, parameterType, single, defaultValue, isObtainedAsCollection, isOptional,
encoded);
this.converter = converter;
this.customerParameterExtractor = customerParameterExtractor;
}
Expand Down

0 comments on commit 4e6a669

Please sign in to comment.