se.fortnox.reactivewizard.jaxrs.params.ParamResolverFactories Maven / Gradle / Ivy
package se.fortnox.reactivewizard.jaxrs.params;
import com.fasterxml.jackson.core.type.TypeReference;
import io.netty.handler.codec.http.HttpResponseStatus;
import jakarta.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Mono;
import se.fortnox.reactivewizard.jaxrs.WebException;
import se.fortnox.reactivewizard.jaxrs.params.annotated.AnnotatedParamResolverFactories;
import se.fortnox.reactivewizard.jaxrs.params.annotated.AnnotatedParamResolverFactory;
import se.fortnox.reactivewizard.jaxrs.params.deserializing.BodyDeserializer;
import se.fortnox.reactivewizard.jaxrs.params.deserializing.DeserializerException;
import se.fortnox.reactivewizard.jaxrs.params.deserializing.DeserializerFactory;
import se.fortnox.reactivewizard.util.ReflectionUtil;
import javax.ws.rs.DefaultValue;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* Creates param resolvers which can resolve method parameters from an incoming request.
*/
public class ParamResolverFactories {
private final DeserializerFactory deserializerFactory;
private final ParamResolvers paramResolvers;
private final AnnotatedParamResolverFactories annotatedParamResolverFactories;
private final ParamTypeResolver paramTypeResolver;
private static final Logger LOG = LoggerFactory.getLogger(ParamResolverFactory.class);
@Inject
public ParamResolverFactories(DeserializerFactory deserializerFactory,
ParamResolvers paramResolvers,
AnnotatedParamResolverFactories annotatedParamResolverFactories,
ParamTypeResolver paramTypeResolver
) {
this.deserializerFactory = deserializerFactory;
this.paramResolvers = paramResolvers;
this.annotatedParamResolverFactories = annotatedParamResolverFactories;
this.paramTypeResolver = paramTypeResolver;
}
public ParamResolverFactories() {
this(new DeserializerFactory(),
new ParamResolvers(),
new AnnotatedParamResolverFactories(),
new WrapSupportingParamTypeResolver());
}
/**
* Create param resolvers.
* @param method the method
* @param consumesAnnotation the consumes requirements
* @return the param resolvers
*/
public List createParamResolvers(Method method, String[] consumesAnnotation) {
List paramResolvers = new ArrayList<>();
Method interfaceMethod = ReflectionUtil.getOverriddenMethod(method);
Parameter[] instanceParameters = method.getParameters();
Parameter[] interfaceParameters = interfaceMethod == null ? instanceParameters : interfaceMethod.getParameters();
for (int i = 0; i < instanceParameters.length; i++) {
TypeReference> paramType = paramTypeResolver.resolveParamType(instanceParameters[i], interfaceParameters[i]);
List parameterAnnotations = ReflectionUtil.getParameterAnnotations(interfaceParameters[i]);
paramResolvers.add(createParamResolver(instanceParameters[i], paramType, parameterAnnotations, consumesAnnotation));
}
return paramResolvers;
}
protected ParamResolver createParamResolver(Parameter parameter,
TypeReference paramType,
List parameterAnnotations,
String[] consumesAnnotation
) {
for (Annotation annotation : parameterAnnotations) {
AnnotatedParamResolverFactory paramResolverFactory = annotatedParamResolverFactories.get(annotation.annotationType());
if (paramResolverFactory != null) {
String defaultValue = findDefaultValue(parameterAnnotations);
return paramResolverFactory.create(paramType, annotation, defaultValue);
}
}
ParamResolverFactory paramResolverFactory = paramResolvers.get((Class)ReflectionUtil.getRawType(paramType.getType()));
if (paramResolverFactory != null) {
ParamResolver paramResolver = paramResolverFactory.createParamResolver(parameter);
if (paramResolver != null) {
return paramResolver;
}
}
BodyDeserializer bodyDeserializer = deserializerFactory.getBodyDeserializer(paramType, consumesAnnotation);
if (bodyDeserializer != null) {
return request -> {
T deserializedBody = deserializeBody(bodyDeserializer, request.getBody());
if (Objects.isNull(deserializedBody)) {
String body = new String(request.getBody(), StandardCharsets.UTF_8);
LOG.warn("Body deserializer returned null when deserializing body: '{}'", body);
return Mono.error(new WebException(HttpResponseStatus.BAD_REQUEST));
}
return Mono.just(deserializedBody);
};
}
throw new RuntimeException("Could not find any deserializer for param of type " + paramType.getType());
}
/**
* Find the value of the DefaultValue annotation.
* @param parameterAnnotations the annotations
* @return default value or null if not found
*/
public static String findDefaultValue(List parameterAnnotations) {
DefaultValue defaultValueAnnotation = findDefaultValueAnnotation(parameterAnnotations);
if (defaultValueAnnotation == null) {
return null;
}
return defaultValueAnnotation.value();
}
/**
* Find the DefaultValue annotation.
* @param parameterAnnotations the annotations
* @return default value annotation or null if not found
*/
public static DefaultValue findDefaultValueAnnotation(List parameterAnnotations) {
for (Annotation annotation : parameterAnnotations) {
if (DefaultValue.class == annotation.annotationType()) {
return (DefaultValue)annotation;
}
}
return null;
}
private T deserializeBody(BodyDeserializer deserializer, byte[] value) {
try {
return deserializer.deserialize(value);
} catch (DeserializerException deserializerException) {
throw new WebException(HttpResponseStatus.BAD_REQUEST, deserializerException.getMessage());
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy