|
|
@ -20,9 +20,12 @@ import feign.DeclarativeContract; |
|
|
|
import feign.MethodMetadata; |
|
|
|
import feign.MethodMetadata; |
|
|
|
import feign.Request; |
|
|
|
import feign.Request; |
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
|
|
|
|
import java.lang.reflect.Field; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import java.lang.reflect.Method; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.Collections; |
|
|
|
import jakarta.ws.rs.*; |
|
|
|
import jakarta.ws.rs.*; |
|
|
|
|
|
|
|
import jakarta.ws.rs.container.Suspended; |
|
|
|
|
|
|
|
import jakarta.ws.rs.core.Context; |
|
|
|
|
|
|
|
|
|
|
|
public class JakartaContract extends DeclarativeContract { |
|
|
|
public class JakartaContract extends DeclarativeContract { |
|
|
|
|
|
|
|
|
|
|
@ -93,6 +96,12 @@ public class JakartaContract extends DeclarativeContract { |
|
|
|
super.registerMethodAnnotation(Consumes.class, this::handleConsumesAnnotation); |
|
|
|
super.registerMethodAnnotation(Consumes.class, this::handleConsumesAnnotation); |
|
|
|
super.registerMethodAnnotation(Produces.class, this::handleProducesAnnotation); |
|
|
|
super.registerMethodAnnotation(Produces.class, this::handleProducesAnnotation); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// parameter with unsupported jax-rs annotations should not be passed as body params.
|
|
|
|
|
|
|
|
// this will prevent interfaces from becoming unusable entirely due to single (unsupported)
|
|
|
|
|
|
|
|
// endpoints.
|
|
|
|
|
|
|
|
// https://github.com/OpenFeign/feign/issues/669
|
|
|
|
|
|
|
|
super.registerParameterAnnotation(Suspended.class, (ann, data, i) -> data.ignoreParamater(i)); |
|
|
|
|
|
|
|
super.registerParameterAnnotation(Context.class, (ann, data, i) -> data.ignoreParamater(i)); |
|
|
|
// trying to minimize the diff
|
|
|
|
// trying to minimize the diff
|
|
|
|
registerParamAnnotations(); |
|
|
|
registerParamAnnotations(); |
|
|
|
} |
|
|
|
} |
|
|
@ -113,37 +122,93 @@ public class JakartaContract extends DeclarativeContract { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
protected void registerParamAnnotations() { |
|
|
|
protected void registerParamAnnotations() { |
|
|
|
{ |
|
|
|
|
|
|
|
registerParameterAnnotation(PathParam.class, (param, data, paramIndex) -> { |
|
|
|
registerParameterAnnotation(PathParam.class, (param, data, paramIndex) -> { |
|
|
|
final String name = param.value(); |
|
|
|
final String name = param.value(); |
|
|
|
checkState(emptyToNull(name) != null, "PathParam.value() was empty on parameter %s", |
|
|
|
checkState(emptyToNull(name) != null, "PathParam.value() was empty on parameter %s", |
|
|
|
paramIndex); |
|
|
|
paramIndex); |
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
}); |
|
|
|
}); |
|
|
|
registerParameterAnnotation(QueryParam.class, (param, data, paramIndex) -> { |
|
|
|
registerParameterAnnotation(QueryParam.class, (param, data, paramIndex) -> { |
|
|
|
final String name = param.value(); |
|
|
|
final String name = param.value(); |
|
|
|
checkState(emptyToNull(name) != null, "QueryParam.value() was empty on parameter %s", |
|
|
|
checkState(emptyToNull(name) != null, "QueryParam.value() was empty on parameter %s", |
|
|
|
paramIndex); |
|
|
|
paramIndex); |
|
|
|
final String query = addTemplatedParam(name); |
|
|
|
final String query = addTemplatedParam(name); |
|
|
|
data.template().query(name, query); |
|
|
|
data.template().query(name, query); |
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
}); |
|
|
|
}); |
|
|
|
registerParameterAnnotation(HeaderParam.class, (param, data, paramIndex) -> { |
|
|
|
registerParameterAnnotation(HeaderParam.class, (param, data, paramIndex) -> { |
|
|
|
final String name = param.value(); |
|
|
|
final String name = param.value(); |
|
|
|
checkState(emptyToNull(name) != null, "HeaderParam.value() was empty on parameter %s", |
|
|
|
checkState(emptyToNull(name) != null, "HeaderParam.value() was empty on parameter %s", |
|
|
|
paramIndex); |
|
|
|
paramIndex); |
|
|
|
final String header = addTemplatedParam(name); |
|
|
|
final String header = addTemplatedParam(name); |
|
|
|
data.template().header(name, header); |
|
|
|
data.template().header(name, header); |
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
}); |
|
|
|
}); |
|
|
|
registerParameterAnnotation(FormParam.class, (param, data, paramIndex) -> { |
|
|
|
registerParameterAnnotation(FormParam.class, (param, data, paramIndex) -> { |
|
|
|
final String name = param.value(); |
|
|
|
final String name = param.value(); |
|
|
|
checkState(emptyToNull(name) != null, "FormParam.value() was empty on parameter %s", |
|
|
|
checkState(emptyToNull(name) != null, "FormParam.value() was empty on parameter %s", |
|
|
|
paramIndex); |
|
|
|
paramIndex); |
|
|
|
data.formParams().add(name); |
|
|
|
data.formParams().add(name); |
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Reflect over the Bean Param looking for supported parameter annotations
|
|
|
|
|
|
|
|
registerParameterAnnotation(BeanParam.class, (param, data, paramIndex) -> { |
|
|
|
|
|
|
|
final Field[] aggregatedParams = data.method() |
|
|
|
|
|
|
|
.getParameters()[paramIndex] |
|
|
|
|
|
|
|
.getType() |
|
|
|
|
|
|
|
.getDeclaredFields(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (Field aggregatedParam : aggregatedParams) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (aggregatedParam.isAnnotationPresent(PathParam.class)) { |
|
|
|
|
|
|
|
final String name = aggregatedParam.getAnnotation(PathParam.class).value(); |
|
|
|
|
|
|
|
checkState( |
|
|
|
|
|
|
|
emptyToNull(name) != null, |
|
|
|
|
|
|
|
"BeanParam parameter %s contains PathParam with empty .value() on field %s", |
|
|
|
|
|
|
|
paramIndex, |
|
|
|
|
|
|
|
aggregatedParam.getName()); |
|
|
|
|
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (aggregatedParam.isAnnotationPresent(QueryParam.class)) { |
|
|
|
|
|
|
|
final String name = aggregatedParam.getAnnotation(QueryParam.class).value(); |
|
|
|
|
|
|
|
checkState( |
|
|
|
|
|
|
|
emptyToNull(name) != null, |
|
|
|
|
|
|
|
"BeanParam parameter %s contains QueryParam with empty .value() on field %s", |
|
|
|
|
|
|
|
paramIndex, |
|
|
|
|
|
|
|
aggregatedParam.getName()); |
|
|
|
|
|
|
|
final String query = addTemplatedParam(name); |
|
|
|
|
|
|
|
data.template().query(name, query); |
|
|
|
|
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (aggregatedParam.isAnnotationPresent(HeaderParam.class)) { |
|
|
|
|
|
|
|
final String name = aggregatedParam.getAnnotation(HeaderParam.class).value(); |
|
|
|
|
|
|
|
checkState( |
|
|
|
|
|
|
|
emptyToNull(name) != null, |
|
|
|
|
|
|
|
"BeanParam parameter %s contains HeaderParam with empty .value() on field %s", |
|
|
|
|
|
|
|
paramIndex, |
|
|
|
|
|
|
|
aggregatedParam.getName()); |
|
|
|
|
|
|
|
final String header = addTemplatedParam(name); |
|
|
|
|
|
|
|
data.template().header(name, header); |
|
|
|
|
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (aggregatedParam.isAnnotationPresent(FormParam.class)) { |
|
|
|
|
|
|
|
final String name = aggregatedParam.getAnnotation(FormParam.class).value(); |
|
|
|
|
|
|
|
checkState( |
|
|
|
|
|
|
|
emptyToNull(name) != null, |
|
|
|
|
|
|
|
"BeanParam parameter %s contains FormParam with empty .value() on field %s", |
|
|
|
|
|
|
|
paramIndex, |
|
|
|
|
|
|
|
aggregatedParam.getName()); |
|
|
|
|
|
|
|
data.formParams().add(name); |
|
|
|
|
|
|
|
nameParam(data, name, paramIndex); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Not using override as the super-type's method is deprecated and will be removed.
|
|
|
|
// Not using override as the super-type's method is deprecated and will be removed.
|
|
|
|