Search in sources :

Example 11 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class RequestArgumentSatisfier method getValueForArgument.

/**
 * @param argument         The argument
 * @param request          The HTTP request
 * @param satisfyOptionals Whether to satisfy optionals
 * @return An {@link Optional} for the value
 */
protected Optional<Object> getValueForArgument(Argument argument, HttpRequest<?> request, boolean satisfyOptionals) {
    Object value = null;
    Optional<ArgumentBinder> registeredBinder = binderRegistry.findArgumentBinder(argument, request);
    if (registeredBinder.isPresent()) {
        ArgumentBinder argumentBinder = registeredBinder.get();
        ArgumentConversionContext conversionContext = ConversionContext.of(argument, request.getLocale().orElse(null), request.getCharacterEncoding());
        if (argumentBinder instanceof BodyArgumentBinder) {
            if (argumentBinder instanceof NonBlockingBodyArgumentBinder) {
                ArgumentBinder.BindingResult bindingResult = argumentBinder.bind(conversionContext, request);
                if (bindingResult.isPresentAndSatisfied()) {
                    value = bindingResult.get();
                } else if (bindingResult.isSatisfied() && argument.isNullable()) {
                    value = NullArgument.INSTANCE;
                }
            } else {
                value = getValueForBlockingBodyArgumentBinder(request, argumentBinder, conversionContext);
            }
        } else if (argumentBinder instanceof RequestBeanAnnotationBinder) {
            // Resolve RequestBean after filters since some field types may depend on filters, i.e. Authentication
            value = (UnresolvedArgument<?>) () -> argumentBinder.bind(conversionContext, request);
        } else {
            ArgumentBinder.BindingResult bindingResult = argumentBinder.bind(conversionContext, request);
            if (argument.getType() == Optional.class) {
                if (bindingResult.isSatisfied() || satisfyOptionals) {
                    Optional optionalValue = bindingResult.getValue();
                    if (optionalValue.isPresent()) {
                        value = optionalValue.get();
                    } else {
                        value = optionalValue;
                    }
                }
            } else if (bindingResult.isPresentAndSatisfied()) {
                value = bindingResult.get();
            } else if (bindingResult.isSatisfied() && argument.isNullable()) {
                value = NullArgument.INSTANCE;
            } else if (HttpMethod.requiresRequestBody(request.getMethod()) || argument.isNullable() || conversionContext.hasErrors()) {
                value = (UnresolvedArgument) () -> {
                    ArgumentBinder.BindingResult result = argumentBinder.bind(conversionContext, request);
                    Optional<ConversionError> lastError = conversionContext.getLastError();
                    if (lastError.isPresent()) {
                        return (ArgumentBinder.BindingResult) () -> lastError;
                    }
                    return result;
                };
            }
        }
    }
    return Optional.ofNullable(value);
}
Also used : NonBlockingBodyArgumentBinder(io.micronaut.http.bind.binders.NonBlockingBodyArgumentBinder) UnresolvedArgument(io.micronaut.web.router.UnresolvedArgument) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) Optional(java.util.Optional) BodyArgumentBinder(io.micronaut.http.bind.binders.BodyArgumentBinder) NonBlockingBodyArgumentBinder(io.micronaut.http.bind.binders.NonBlockingBodyArgumentBinder) RequestBeanAnnotationBinder(io.micronaut.http.bind.binders.RequestBeanAnnotationBinder) BodyArgumentBinder(io.micronaut.http.bind.binders.BodyArgumentBinder) ArgumentBinder(io.micronaut.core.bind.ArgumentBinder) NonBlockingBodyArgumentBinder(io.micronaut.http.bind.binders.NonBlockingBodyArgumentBinder)

Example 12 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class MultipartBodyArgumentBinder method bind.

@Override
public BindingResult<MultipartBody> bind(ArgumentConversionContext<MultipartBody> context, HttpRequest<?> source) {
    if (source instanceof NettyHttpRequest) {
        NettyHttpRequest nettyHttpRequest = (NettyHttpRequest) source;
        io.netty.handler.codec.http.HttpRequest nativeRequest = nettyHttpRequest.getNativeRequest();
        if (nativeRequest instanceof StreamedHttpRequest) {
            HttpContentProcessor<?> processor = beanLocator.findBean(HttpContentSubscriberFactory.class, new ConsumesMediaTypeQualifier<>(MediaType.MULTIPART_FORM_DATA_TYPE)).map(factory -> factory.build(nettyHttpRequest)).orElse(new DefaultHttpContentProcessor(nettyHttpRequest, httpServerConfiguration.get()));
            // noinspection unchecked
            return () -> Optional.of(subscriber -> processor.subscribe(new TypedSubscriber<Object>((Argument) context.getArgument()) {

                Subscription s;

                AtomicLong partsRequested = new AtomicLong(0);

                @Override
                protected void doOnSubscribe(Subscription subscription) {
                    this.s = subscription;
                    subscriber.onSubscribe(new Subscription() {

                        @Override
                        public void request(long n) {
                            if (partsRequested.getAndUpdate(prev -> prev + n) == 0) {
                                s.request(n);
                            }
                        }

                        @Override
                        public void cancel() {
                            subscription.cancel();
                        }
                    });
                }

                @Override
                protected void doOnNext(Object message) {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Server received streaming message for argument [{}]: {}", context.getArgument(), message);
                    }
                    if (message instanceof ByteBufHolder && ((ByteBufHolder) message).content() instanceof EmptyByteBuf) {
                        return;
                    }
                    if (message instanceof HttpData) {
                        HttpData data = (HttpData) message;
                        if (data.isCompleted()) {
                            partsRequested.decrementAndGet();
                            if (data instanceof FileUpload) {
                                subscriber.onNext(new NettyCompletedFileUpload((FileUpload) data, false));
                            } else if (data instanceof Attribute) {
                                subscriber.onNext(new NettyCompletedAttribute((Attribute) data, false));
                            }
                            // If the user didn't release the data, we should
                            if (data.refCnt() > 0) {
                                data.release();
                            }
                        }
                    }
                    if (partsRequested.get() > 0) {
                        s.request(1);
                    }
                }

                @Override
                protected void doOnError(Throwable t) {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Server received error for argument [" + context.getArgument() + "]: " + t.getMessage(), t);
                    }
                    try {
                        subscriber.onError(t);
                    } finally {
                        s.cancel();
                    }
                }

                @Override
                protected void doOnComplete() {
                    if (LOG.isTraceEnabled()) {
                        LOG.trace("Done receiving messages for argument: {}", context.getArgument());
                    }
                    subscriber.onComplete();
                }
            }));
        }
    }
    return BindingResult.EMPTY;
}
Also used : ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) LoggerFactory(org.slf4j.LoggerFactory) DefaultHttpContentProcessor(io.micronaut.http.server.netty.DefaultHttpContentProcessor) Internal(io.micronaut.core.annotation.Internal) ByteBufHolder(io.netty.buffer.ByteBufHolder) HttpContentProcessor(io.micronaut.http.server.netty.HttpContentProcessor) TypedSubscriber(io.micronaut.core.async.subscriber.TypedSubscriber) NonBlockingBodyArgumentBinder(io.micronaut.http.bind.binders.NonBlockingBodyArgumentBinder) MediaType(io.micronaut.http.MediaType) HttpData(io.netty.handler.codec.http.multipart.HttpData) Argument(io.micronaut.core.type.Argument) HttpRequest(io.micronaut.http.HttpRequest) BeanLocator(io.micronaut.context.BeanLocator) NettyHttpRequest(io.micronaut.http.server.netty.NettyHttpRequest) NettyHttpServer(io.micronaut.http.server.netty.NettyHttpServer) Logger(org.slf4j.Logger) MultipartBody(io.micronaut.http.server.multipart.MultipartBody) FileUpload(io.netty.handler.codec.http.multipart.FileUpload) HttpServerConfiguration(io.micronaut.http.server.HttpServerConfiguration) HttpContentSubscriberFactory(io.micronaut.http.server.netty.HttpContentSubscriberFactory) Attribute(io.netty.handler.codec.http.multipart.Attribute) AtomicLong(java.util.concurrent.atomic.AtomicLong) StreamedHttpRequest(io.micronaut.http.netty.stream.StreamedHttpRequest) EmptyByteBuf(io.netty.buffer.EmptyByteBuf) BeanProvider(io.micronaut.context.BeanProvider) Subscription(org.reactivestreams.Subscription) Optional(java.util.Optional) ConsumesMediaTypeQualifier(io.micronaut.web.router.qualifier.ConsumesMediaTypeQualifier) EmptyByteBuf(io.netty.buffer.EmptyByteBuf) Attribute(io.netty.handler.codec.http.multipart.Attribute) StreamedHttpRequest(io.micronaut.http.netty.stream.StreamedHttpRequest) AtomicLong(java.util.concurrent.atomic.AtomicLong) DefaultHttpContentProcessor(io.micronaut.http.server.netty.DefaultHttpContentProcessor) HttpData(io.netty.handler.codec.http.multipart.HttpData) ByteBufHolder(io.netty.buffer.ByteBufHolder) NettyHttpRequest(io.micronaut.http.server.netty.NettyHttpRequest) Subscription(org.reactivestreams.Subscription) TypedSubscriber(io.micronaut.core.async.subscriber.TypedSubscriber) FileUpload(io.netty.handler.codec.http.multipart.FileUpload)

Example 13 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class AbstractBeanDefinition method getValueForField.

/**
 * Obtains a value for the given field from the bean context
 * <p>
 * Warning: this method is used by internal generated code and should not be called by user code.
 *
 * @param resolutionContext The resolution context
 * @param context           The context
 * @param fieldIndex        The index of the field
 * @return The resolved bean
 */
@SuppressWarnings("WeakerAccess")
@Internal
@UsedByGeneratedCode
protected final Object getValueForField(BeanResolutionContext resolutionContext, BeanContext context, int fieldIndex) {
    FieldInjectionPoint injectionPoint = fieldInjectionPoints.get(fieldIndex);
    BeanResolutionContext.Path path = resolutionContext.getPath();
    path.pushFieldResolve(this, injectionPoint);
    try {
        if (context instanceof PropertyResolver) {
            final AnnotationMetadata annotationMetadata = injectionPoint.getAnnotationMetadata();
            String valueAnnVal = annotationMetadata.stringValue(Value.class).orElse(null);
            Argument<?> fieldArgument = injectionPoint.asArgument();
            Argument<?> argumentType;
            boolean isCollection = false;
            if (Collection.class.isAssignableFrom(injectionPoint.getType())) {
                argumentType = fieldArgument.getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT);
                isCollection = true;
            } else {
                argumentType = fieldArgument;
            }
            if (isInnerConfiguration(argumentType, context)) {
                Qualifier qualifier = resolveQualifier(resolutionContext, fieldArgument, true);
                if (isCollection) {
                    Collection beans = ((DefaultBeanContext) context).getBeansOfType(resolutionContext, argumentType, qualifier);
                    return coerceCollectionToCorrectType(fieldArgument.getType(), beans);
                } else {
                    return ((DefaultBeanContext) context).getBean(resolutionContext, argumentType, qualifier);
                }
            } else {
                String valString = resolvePropertyValueName(resolutionContext, injectionPoint, valueAnnVal, annotationMetadata);
                ArgumentConversionContext conversionContext = ConversionContext.of(fieldArgument);
                Optional value = resolveValue((ApplicationContext) context, conversionContext, valueAnnVal != null, valString);
                if (argumentType.isOptional()) {
                    return resolveOptionalObject(value);
                } else {
                    if (value.isPresent()) {
                        return value.get();
                    } else {
                        if (fieldArgument.isDeclaredNullable()) {
                            return null;
                        }
                        throw new DependencyInjectionException(resolutionContext, injectionPoint, "Error resolving field value [" + valString + "]. Property doesn't exist or cannot be converted");
                    }
                }
            }
        } else {
            throw new DependencyInjectionException(resolutionContext, injectionPoint, "@Value requires a BeanContext that implements PropertyResolver");
        }
    } finally {
        path.pop();
    }
}
Also used : PropertyResolver(io.micronaut.core.value.PropertyResolver) AbstractEnvironmentAnnotationMetadata(io.micronaut.inject.annotation.AbstractEnvironmentAnnotationMetadata) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) TypeAnnotationQualifier(io.micronaut.inject.qualifiers.TypeAnnotationQualifier) InterceptorBindingQualifier(io.micronaut.inject.qualifiers.InterceptorBindingQualifier)

Example 14 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class AbstractRouteMatch method fulfill.

@Override
public RouteMatch<R> fulfill(Map<String, Object> argumentValues) {
    if (CollectionUtils.isEmpty(argumentValues)) {
        return this;
    } else {
        Map<String, Object> oldVariables = getVariableValues();
        Map<String, Object> newVariables = new LinkedHashMap<>(oldVariables);
        final Argument<?> bodyArgument = getBodyArgument().orElse(null);
        Argument[] arguments = getArguments();
        Collection<Argument> requiredArguments = getRequiredArguments();
        boolean hasRequiredArguments = CollectionUtils.isNotEmpty(requiredArguments);
        for (Argument requiredArgument : arguments) {
            String argumentName = requiredArgument.getName();
            if (argumentValues.containsKey(argumentName)) {
                Object value = argumentValues.get(argumentName);
                if (bodyArgument != null && bodyArgument.getName().equals(argumentName)) {
                    requiredArgument = bodyArgument;
                }
                if (hasRequiredArguments) {
                    requiredArguments.remove(requiredArgument);
                }
                if (value != null) {
                    String name = abstractRoute.resolveInputName(requiredArgument);
                    if (value instanceof UnresolvedArgument || value instanceof NullArgument) {
                        newVariables.put(name, value);
                    } else {
                        Class type = requiredArgument.getType();
                        if (type.isInstance(value)) {
                            newVariables.put(name, value);
                        } else {
                            ArgumentConversionContext conversionContext = ConversionContext.of(requiredArgument);
                            Optional converted = conversionService.convert(value, conversionContext);
                            Object result = converted.isPresent() ? converted.get() : conversionContext.getLastError().orElse(null);
                            if (result != null) {
                                newVariables.put(name, result);
                            }
                        }
                    }
                }
            }
        }
        return newFulfilled(newVariables, (List<Argument>) requiredArguments);
    }
}
Also used : Argument(io.micronaut.core.type.Argument) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext)

Example 15 with ArgumentConversionContext

use of io.micronaut.core.convert.ArgumentConversionContext in project micronaut-core by micronaut-projects.

the class HttpClientIntroductionAdvice method intercept.

/**
 * Interceptor to apply headers, cookies, parameter and body arguements.
 *
 * @param context The context
 * @return httpClient or future
 */
@Nullable
@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
    if (!context.hasStereotype(Client.class)) {
        throw new IllegalStateException("Client advice called from type that is not annotated with @Client: " + context);
    }
    final AnnotationMetadata annotationMetadata = context.getAnnotationMetadata();
    Class<?> declaringType = context.getDeclaringType();
    if (Closeable.class == declaringType || AutoCloseable.class == declaringType) {
        clientFactory.disposeClient(annotationMetadata);
        return null;
    }
    Optional<Class<? extends Annotation>> httpMethodMapping = context.getAnnotationTypeByStereotype(HttpMethodMapping.class);
    HttpClient httpClient = clientFactory.getClient(annotationMetadata);
    if (context.hasStereotype(HttpMethodMapping.class) && httpClient != null) {
        AnnotationValue<HttpMethodMapping> mapping = context.getAnnotation(HttpMethodMapping.class);
        String uri = mapping.getRequiredValue(String.class);
        if (StringUtils.isEmpty(uri)) {
            uri = "/" + context.getMethodName();
        }
        Class<? extends Annotation> annotationType = httpMethodMapping.get();
        HttpMethod httpMethod = HttpMethod.parse(annotationType.getSimpleName().toUpperCase(Locale.ENGLISH));
        String httpMethodName = context.stringValue(CustomHttpMethod.class, "method").orElse(httpMethod.name());
        MutableHttpRequest<?> request = HttpRequest.create(httpMethod, "", httpMethodName);
        UriMatchTemplate uriTemplate = UriMatchTemplate.of("");
        if (!(uri.length() == 1 && uri.charAt(0) == '/')) {
            uriTemplate = uriTemplate.nest(uri);
        }
        Map<String, Object> pathParams = new HashMap<>();
        Map<String, List<String>> queryParams = new LinkedHashMap<>();
        ClientRequestUriContext uriContext = new ClientRequestUriContext(uriTemplate, pathParams, queryParams);
        List<Argument> bodyArguments = new ArrayList<>();
        List<String> uriVariables = uriTemplate.getVariableNames();
        Map<String, MutableArgumentValue<?>> parameters = context.getParameters();
        ClientArgumentRequestBinder<Object> defaultBinder = (ctx, uriCtx, value, req) -> {
            Argument<?> argument = ctx.getArgument();
            if (uriCtx.getUriTemplate().getVariableNames().contains(argument.getName())) {
                String name = argument.getAnnotationMetadata().stringValue(Bindable.class).orElse(argument.getName());
                // Convert and put as path param
                if (argument.getAnnotationMetadata().hasStereotype(Format.class)) {
                    ConversionService.SHARED.convert(value, ConversionContext.STRING.with(argument.getAnnotationMetadata())).ifPresent(v -> pathParams.put(name, v));
                } else {
                    pathParams.put(name, value);
                }
            } else {
                bodyArguments.add(ctx.getArgument());
            }
        };
        // Apply all the method binders
        List<Class<? extends Annotation>> methodBinderTypes = context.getAnnotationTypesByStereotype(Bindable.class);
        // @Version is not a bindable, so it needs to looked for separately
        methodBinderTypes.addAll(context.getAnnotationTypesByStereotype(Version.class));
        if (!CollectionUtils.isEmpty(methodBinderTypes)) {
            for (Class<? extends Annotation> binderType : methodBinderTypes) {
                binderRegistry.findAnnotatedBinder(binderType).ifPresent(b -> b.bind(context, uriContext, request));
            }
        }
        InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
        // Apply all the argument binders
        Argument[] arguments = context.getArguments();
        if (arguments.length > 0) {
            for (Argument argument : arguments) {
                Object definedValue = getValue(argument, context, parameters);
                if (definedValue != null) {
                    final ClientArgumentRequestBinder<Object> binder = (ClientArgumentRequestBinder<Object>) binderRegistry.findArgumentBinder((Argument<Object>) argument).orElse(defaultBinder);
                    ArgumentConversionContext conversionContext = ConversionContext.of(argument);
                    binder.bind(conversionContext, uriContext, definedValue, request);
                    if (conversionContext.hasErrors()) {
                        return interceptedMethod.handleException(new ConversionErrorException(argument, conversionContext.getLastError().get()));
                    }
                }
            }
        }
        Object body = request.getBody().orElse(null);
        if (body == null && !bodyArguments.isEmpty()) {
            Map<String, Object> bodyMap = new LinkedHashMap<>();
            for (Argument bodyArgument : bodyArguments) {
                String argumentName = bodyArgument.getName();
                MutableArgumentValue<?> value = parameters.get(argumentName);
                bodyMap.put(argumentName, value.getValue());
            }
            body = bodyMap;
            request.body(body);
        }
        boolean variableSatisfied = uriVariables.isEmpty() || pathParams.keySet().containsAll(uriVariables);
        if (body != null && !variableSatisfied) {
            if (body instanceof Map) {
                for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) body).entrySet()) {
                    String k = entry.getKey().toString();
                    Object v = entry.getValue();
                    if (v != null) {
                        pathParams.putIfAbsent(k, v);
                    }
                }
            } else {
                BeanMap<Object> beanMap = BeanMap.of(body);
                for (Map.Entry<String, Object> entry : beanMap.entrySet()) {
                    String k = entry.getKey();
                    Object v = entry.getValue();
                    if (v != null) {
                        pathParams.putIfAbsent(k, v);
                    }
                }
            }
        }
        if (!HttpMethod.permitsRequestBody(httpMethod)) {
            // If a binder set the body and the method does not permit it, reset to null
            request.body(null);
            body = null;
        }
        uri = uriTemplate.expand(pathParams);
        // Remove all the pathParams that have already been used.
        // Other path parameters are added to query
        uriVariables.forEach(pathParams::remove);
        addParametersToQuery(pathParams, uriContext);
        // The original query can be added by getting it from the request.getUri() and appending
        request.uri(URI.create(appendQuery(uri, uriContext.getQueryParameters())));
        if (body != null && !request.getContentType().isPresent()) {
            MediaType[] contentTypes = MediaType.of(context.stringValues(Produces.class));
            if (ArrayUtils.isEmpty(contentTypes)) {
                contentTypes = DEFAULT_ACCEPT_TYPES;
            }
            if (ArrayUtils.isNotEmpty(contentTypes)) {
                request.contentType(contentTypes[0]);
            }
        }
        request.setAttribute(HttpAttributes.INVOCATION_CONTEXT, context);
        // Set the URI template used to make the request for tracing purposes
        request.setAttribute(HttpAttributes.URI_TEMPLATE, resolveTemplate(annotationMetadata, uriTemplate.toString()));
        String serviceId = getClientId(annotationMetadata);
        Argument<?> errorType = annotationMetadata.classValue(Client.class, "errorType").map((Function<Class, Argument>) Argument::of).orElse(HttpClient.DEFAULT_ERROR_TYPE);
        request.setAttribute(HttpAttributes.SERVICE_ID, serviceId);
        final MediaType[] acceptTypes;
        Collection<MediaType> accept = request.accept();
        if (accept.isEmpty()) {
            String[] consumesMediaType = context.stringValues(Consumes.class);
            if (ArrayUtils.isEmpty(consumesMediaType)) {
                acceptTypes = DEFAULT_ACCEPT_TYPES;
            } else {
                acceptTypes = MediaType.of(consumesMediaType);
            }
            request.accept(acceptTypes);
        } else {
            acceptTypes = accept.toArray(MediaType.EMPTY_ARRAY);
        }
        ReturnType<?> returnType = context.getReturnType();
        try {
            Argument<?> valueType = interceptedMethod.returnTypeValue();
            Class<?> reactiveValueType = valueType.getType();
            switch(interceptedMethod.resultType()) {
                case PUBLISHER:
                    boolean isSingle = returnType.isSingleResult() || returnType.isCompletable() || HttpResponse.class.isAssignableFrom(reactiveValueType) || HttpStatus.class == reactiveValueType;
                    Publisher<?> publisher;
                    if (!isSingle && httpClient instanceof StreamingHttpClient) {
                        publisher = httpClientResponseStreamingPublisher((StreamingHttpClient) httpClient, acceptTypes, request, errorType, valueType);
                    } else {
                        publisher = httpClientResponsePublisher(httpClient, request, returnType, errorType, valueType);
                    }
                    Object finalPublisher = interceptedMethod.handleResult(publisher);
                    for (ReactiveClientResultTransformer transformer : transformers) {
                        finalPublisher = transformer.transform(finalPublisher);
                    }
                    return finalPublisher;
                case COMPLETION_STAGE:
                    Publisher<?> csPublisher = httpClientResponsePublisher(httpClient, request, returnType, errorType, valueType);
                    CompletableFuture<Object> future = new CompletableFuture<>();
                    csPublisher.subscribe(new CompletionAwareSubscriber<Object>() {

                        AtomicReference<Object> reference = new AtomicReference<>();

                        @Override
                        protected void doOnSubscribe(Subscription subscription) {
                            subscription.request(1);
                        }

                        @Override
                        protected void doOnNext(Object message) {
                            if (Void.class != reactiveValueType) {
                                reference.set(message);
                            }
                        }

                        @Override
                        protected void doOnError(Throwable t) {
                            if (t instanceof HttpClientResponseException) {
                                HttpClientResponseException e = (HttpClientResponseException) t;
                                if (e.getStatus() == HttpStatus.NOT_FOUND) {
                                    if (reactiveValueType == Optional.class) {
                                        future.complete(Optional.empty());
                                    } else if (HttpResponse.class.isAssignableFrom(reactiveValueType)) {
                                        future.complete(e.getResponse());
                                    } else {
                                        future.complete(null);
                                    }
                                    return;
                                }
                            }
                            if (LOG.isErrorEnabled()) {
                                LOG.error("Client [" + declaringType.getName() + "] received HTTP error response: " + t.getMessage(), t);
                            }
                            future.completeExceptionally(t);
                        }

                        @Override
                        protected void doOnComplete() {
                            future.complete(reference.get());
                        }
                    });
                    return interceptedMethod.handleResult(future);
                case SYNCHRONOUS:
                    Class<?> javaReturnType = returnType.getType();
                    BlockingHttpClient blockingHttpClient = httpClient.toBlocking();
                    if (void.class == javaReturnType || httpMethod == HttpMethod.HEAD) {
                        request.getHeaders().remove(HttpHeaders.ACCEPT);
                    }
                    if (HttpResponse.class.isAssignableFrom(javaReturnType)) {
                        return handleBlockingCall(javaReturnType, () -> blockingHttpClient.exchange(request, returnType.asArgument().getFirstTypeVariable().orElse(Argument.OBJECT_ARGUMENT), errorType));
                    } else if (void.class == javaReturnType) {
                        return handleBlockingCall(javaReturnType, () -> blockingHttpClient.exchange(request, null, errorType));
                    } else {
                        return handleBlockingCall(javaReturnType, () -> blockingHttpClient.retrieve(request, returnType.asArgument(), errorType));
                    }
                default:
                    return interceptedMethod.unsupported();
            }
        } catch (Exception e) {
            return interceptedMethod.handleException(e);
        }
    }
    // try other introduction advice
    return context.proceed();
}
Also used : Publishers(io.micronaut.core.async.publisher.Publishers) Bindable(io.micronaut.core.bind.annotation.Bindable) Arrays(java.util.Arrays) Version(io.micronaut.core.version.annotation.Version) CustomHttpMethod(io.micronaut.http.annotation.CustomHttpMethod) Produces(io.micronaut.http.annotation.Produces) ArrayUtils(io.micronaut.core.util.ArrayUtils) LoggerFactory(org.slf4j.LoggerFactory) HttpHeaders(io.micronaut.http.HttpHeaders) SseClient(io.micronaut.http.client.sse.SseClient) Internal(io.micronaut.core.annotation.Internal) Event(io.micronaut.http.sse.Event) CompletionAwareSubscriber(io.micronaut.core.async.subscriber.CompletionAwareSubscriber) HttpStatus(io.micronaut.http.HttpStatus) MediaType(io.micronaut.http.MediaType) Locale(java.util.Locale) Map(java.util.Map) ClientArgumentRequestBinder(io.micronaut.http.client.bind.ClientArgumentRequestBinder) HttpResponse(io.micronaut.http.HttpResponse) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) URI(java.net.URI) HttpClient(io.micronaut.http.client.HttpClient) JsonMediaTypeCodec(io.micronaut.json.codec.JsonMediaTypeCodec) MutableArgumentValue(io.micronaut.core.type.MutableArgumentValue) Collection(java.util.Collection) Singleton(jakarta.inject.Singleton) HttpClientBinderRegistry(io.micronaut.http.client.bind.HttpClientBinderRegistry) StringUtils(io.micronaut.core.util.StringUtils) Format(io.micronaut.core.convert.format.Format) List(java.util.List) MethodInvocationContext(io.micronaut.aop.MethodInvocationContext) AnnotationValue(io.micronaut.core.annotation.AnnotationValue) Annotation(java.lang.annotation.Annotation) Optional(java.util.Optional) HttpAttributes(io.micronaut.http.HttpAttributes) StreamingHttpClient(io.micronaut.http.client.StreamingHttpClient) MutableHttpRequest(io.micronaut.http.MutableHttpRequest) HttpClientRegistry(io.micronaut.http.client.HttpClientRegistry) UriBuilder(io.micronaut.http.uri.UriBuilder) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) HttpMethodMapping(io.micronaut.http.annotation.HttpMethodMapping) ReactiveClientResultTransformer(io.micronaut.http.client.ReactiveClientResultTransformer) ConversionErrorException(io.micronaut.core.convert.exceptions.ConversionErrorException) UriMatchTemplate(io.micronaut.http.uri.UriMatchTemplate) HashMap(java.util.HashMap) CompletableFuture(java.util.concurrent.CompletableFuture) Client(io.micronaut.http.client.annotation.Client) InterceptedMethod(io.micronaut.aop.InterceptedMethod) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) Supplier(java.util.function.Supplier) BeanMap(io.micronaut.core.beans.BeanMap) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) BlockingHttpClient(io.micronaut.http.client.BlockingHttpClient) MethodInterceptor(io.micronaut.aop.MethodInterceptor) BootstrapContextCompatible(io.micronaut.context.annotation.BootstrapContextCompatible) Nullable(io.micronaut.core.annotation.Nullable) ByteBuffer(io.micronaut.core.io.buffer.ByteBuffer) ReturnType(io.micronaut.core.type.ReturnType) Argument(io.micronaut.core.type.Argument) HttpRequest(io.micronaut.http.HttpRequest) ClientRequestUriContext(io.micronaut.http.client.bind.ClientRequestUriContext) ConversionService(io.micronaut.core.convert.ConversionService) ConfigurationException(io.micronaut.context.exceptions.ConfigurationException) HttpMethod(io.micronaut.http.HttpMethod) Logger(org.slf4j.Logger) Publisher(org.reactivestreams.Publisher) ConversionContext(io.micronaut.core.convert.ConversionContext) CollectionUtils(io.micronaut.core.util.CollectionUtils) Consumes(io.micronaut.http.annotation.Consumes) Subscription(org.reactivestreams.Subscription) Closeable(java.io.Closeable) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) Collections(java.util.Collections) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Closeable(java.io.Closeable) ArrayList(java.util.ArrayList) CustomHttpMethod(io.micronaut.http.annotation.CustomHttpMethod) AnnotationMetadata(io.micronaut.core.annotation.AnnotationMetadata) LinkedHashMap(java.util.LinkedHashMap) Version(io.micronaut.core.version.annotation.Version) MediaType(io.micronaut.http.MediaType) List(java.util.List) ArrayList(java.util.ArrayList) ClientArgumentRequestBinder(io.micronaut.http.client.bind.ClientArgumentRequestBinder) SseClient(io.micronaut.http.client.sse.SseClient) HttpClient(io.micronaut.http.client.HttpClient) StreamingHttpClient(io.micronaut.http.client.StreamingHttpClient) Client(io.micronaut.http.client.annotation.Client) BlockingHttpClient(io.micronaut.http.client.BlockingHttpClient) Subscription(org.reactivestreams.Subscription) Optional(java.util.Optional) HttpStatus(io.micronaut.http.HttpStatus) BlockingHttpClient(io.micronaut.http.client.BlockingHttpClient) ClientRequestUriContext(io.micronaut.http.client.bind.ClientRequestUriContext) Produces(io.micronaut.http.annotation.Produces) Map(java.util.Map) HashMap(java.util.HashMap) BeanMap(io.micronaut.core.beans.BeanMap) LinkedHashMap(java.util.LinkedHashMap) CustomHttpMethod(io.micronaut.http.annotation.CustomHttpMethod) HttpMethod(io.micronaut.http.HttpMethod) StreamingHttpClient(io.micronaut.http.client.StreamingHttpClient) Argument(io.micronaut.core.type.Argument) ConversionErrorException(io.micronaut.core.convert.exceptions.ConversionErrorException) UriMatchTemplate(io.micronaut.http.uri.UriMatchTemplate) Function(java.util.function.Function) CompletableFuture(java.util.concurrent.CompletableFuture) Format(io.micronaut.core.convert.format.Format) ArgumentConversionContext(io.micronaut.core.convert.ArgumentConversionContext) ReactiveClientResultTransformer(io.micronaut.http.client.ReactiveClientResultTransformer) InterceptedMethod(io.micronaut.aop.InterceptedMethod) HttpMethodMapping(io.micronaut.http.annotation.HttpMethodMapping) MutableArgumentValue(io.micronaut.core.type.MutableArgumentValue) AtomicReference(java.util.concurrent.atomic.AtomicReference) Annotation(java.lang.annotation.Annotation) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) ConversionErrorException(io.micronaut.core.convert.exceptions.ConversionErrorException) ConfigurationException(io.micronaut.context.exceptions.ConfigurationException) HttpClientResponseException(io.micronaut.http.client.exceptions.HttpClientResponseException) HttpClient(io.micronaut.http.client.HttpClient) StreamingHttpClient(io.micronaut.http.client.StreamingHttpClient) BlockingHttpClient(io.micronaut.http.client.BlockingHttpClient) Nullable(io.micronaut.core.annotation.Nullable)

Aggregations

ArgumentConversionContext (io.micronaut.core.convert.ArgumentConversionContext)17 Argument (io.micronaut.core.type.Argument)12 Optional (java.util.Optional)9 AnnotationMetadata (io.micronaut.core.annotation.AnnotationMetadata)5 ConversionContext (io.micronaut.core.convert.ConversionContext)5 ConversionService (io.micronaut.core.convert.ConversionService)5 ConversionErrorException (io.micronaut.core.convert.exceptions.ConversionErrorException)5 HttpRequest (io.micronaut.http.HttpRequest)5 Collection (java.util.Collection)5 ConversionError (io.micronaut.core.convert.ConversionError)4 Collections (java.util.Collections)4 ConfigurationException (io.micronaut.context.exceptions.ConfigurationException)3 Internal (io.micronaut.core.annotation.Internal)3 Nullable (io.micronaut.core.annotation.Nullable)3 ArgumentBinder (io.micronaut.core.bind.ArgumentBinder)3 AbstractAnnotatedArgumentBinder (io.micronaut.core.bind.annotation.AbstractAnnotatedArgumentBinder)3 Collectors (java.util.stream.Collectors)3 AnnotationValue (io.micronaut.core.annotation.AnnotationValue)2 NonNull (io.micronaut.core.annotation.NonNull)2 Bindable (io.micronaut.core.bind.annotation.Bindable)2