Search in sources :

Example 1 with CoherencePublisher

use of io.micronaut.coherence.annotation.CoherencePublisher in project micronaut-coherence by micronaut-projects.

the class CoherencePublisherIntroductionAdvice method intercept.

@Override
public Object intercept(MethodInvocationContext<Object, Object> context) {
    if (context.hasAnnotation(CoherencePublisher.class)) {
        // Make sure the CoherencePublisher annotation is present
        context.findAnnotation(CoherencePublisher.class).orElseThrow(() -> new IllegalStateException("No @CoherencePublisher annotation present on method: " + context));
        String topicName = Utils.getFirstTopicName(context).orElse(null);
        String sessionName = context.stringValue(SessionName.class).orElse(Coherence.DEFAULT_NAME);
        Duration maxBlock = context.getValue(CoherencePublisher.class, "maxBlock", Duration.class).orElse(null);
        Argument<?> bodyArgument = null;
        Argument<?>[] arguments = context.getArguments();
        Object[] parameterValues = context.getParameterValues();
        int valueIndex = -1;
        for (int i = 0; i < arguments.length; i++) {
            Argument<?> argument = arguments[i];
            if (argument.isAnnotationPresent(MessageBody.class)) {
                bodyArgument = argument;
                valueIndex = i;
            } else if (argument.isAnnotationPresent(Topics.class) || argument.isAnnotationPresent(Topic.class)) {
                Object o = parameterValues[i];
                if (o != null) {
                    topicName = o.toString();
                }
            }
        }
        if (StringUtils.isEmpty(topicName)) {
            throw new MessagingClientException("No topic specified for method: " + context);
        }
        if (bodyArgument == null) {
            for (int i = 0; i < arguments.length; i++) {
                Argument<?> argument = arguments[i];
                if (!argument.getAnnotationMetadata().hasStereotype(Bindable.class)) {
                    bodyArgument = argument;
                    valueIndex = i;
                    break;
                }
            }
        }
        if (bodyArgument == null) {
            throw new MessagingClientException("No valid message body argument found for method: " + context);
        }
        Object value = parameterValues[valueIndex];
        ReturnType<Object> returnType = context.getReturnType();
        Class<?> javaReturnType = returnType.getType();
        Publisher<Object> publisher = getPublisher(topicName, sessionName);
        boolean isReactiveReturnType = Publishers.isConvertibleToPublisher(javaReturnType);
        boolean isReactiveValue = value != null && Publishers.isConvertibleToPublisher(value.getClass());
        InterceptedMethod interceptedMethod = InterceptedMethod.of(context);
        if (isReactiveReturnType) {
            // return type is a reactive type
            Flux<?> flux = buildSendFlux(context, publisher, Argument.OBJECT_ARGUMENT, maxBlock, value);
            return Publishers.convertPublisher(flux, javaReturnType);
        } else {
            // return type is a future - must be future of Void
            Argument<?> returnArg = returnType.getFirstTypeVariable().orElse(Argument.of(Void.class));
            if (returnArg.getType() != Void.class) {
                throw new MessagingClientException("Generic return type for method must be Void, i.e. CompletableFuture<Void> - " + context);
            }
            CompletableFuture<Void> completableFuture = new CompletableFuture<>();
            if (isReactiveValue) {
                // return type is a future and value is reactive
                Flux<?> sendFlux = buildSendFlux(context, publisher, returnArg, maxBlock, value);
                if (!Publishers.isSingle(value.getClass())) {
                    sendFlux = sendFlux.collectList().flux();
                }
                // noinspection ReactiveStreamsSubscriberImplementation
                sendFlux.subscribe(new Subscriber<Object>() {

                    @Override
                    public void onSubscribe(Subscription s) {
                        s.request(1);
                    }

                    @Override
                    public void onNext(Object o) {
                    }

                    @Override
                    public void onError(Throwable t) {
                        completableFuture.completeExceptionally(wrapException(context, t));
                    }

                    @Override
                    public void onComplete() {
                        completableFuture.complete(null);
                    }
                });
            } else {
                // return type is a future and value is single message
                publisher.publish(value).handle((status, exception) -> {
                    if (exception != null) {
                        completableFuture.completeExceptionally(wrapException(context, exception));
                    } else {
                        completableFuture.complete(null);
                    }
                    return null;
                });
            }
            return interceptedMethod.handleResult(completableFuture);
        }
    } else {
        // can't be implemented so proceed
        return context.proceed();
    }
}
Also used : Argument(io.micronaut.core.type.Argument) CompletableFuture(java.util.concurrent.CompletableFuture) MessagingClientException(io.micronaut.messaging.exceptions.MessagingClientException) Subscription(org.reactivestreams.Subscription) CoherencePublisher(io.micronaut.coherence.annotation.CoherencePublisher) InterceptedMethod(io.micronaut.aop.InterceptedMethod) Bindable(io.micronaut.core.bind.annotation.Bindable) Duration(java.time.Duration) SessionName(io.micronaut.coherence.annotation.SessionName)

Aggregations

InterceptedMethod (io.micronaut.aop.InterceptedMethod)1 CoherencePublisher (io.micronaut.coherence.annotation.CoherencePublisher)1 SessionName (io.micronaut.coherence.annotation.SessionName)1 Bindable (io.micronaut.core.bind.annotation.Bindable)1 Argument (io.micronaut.core.type.Argument)1 MessagingClientException (io.micronaut.messaging.exceptions.MessagingClientException)1 Duration (java.time.Duration)1 CompletableFuture (java.util.concurrent.CompletableFuture)1 Subscription (org.reactivestreams.Subscription)1