Skip to content

Commit

Permalink
Fix issue returning CompletableFuture
Browse files Browse the repository at this point in the history
Closes gh-628
  • Loading branch information
rstoyanchev committed Mar 8, 2023
1 parent 3586ede commit 9066c40
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -16,6 +16,7 @@
package org.springframework.graphql.data.method.annotation.support;

import java.util.Arrays;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

import graphql.schema.DataFetchingEnvironment;
Expand Down Expand Up @@ -133,11 +134,14 @@ public Object invoke(DataFetchingEnvironment environment) {
}) :
toArgsMono(args).flatMap(argValues -> {
Object result = validateAndInvoke(argValues, environment);
if (result instanceof Mono) {
if (result instanceof Mono<?>) {
return (Mono<?>) result;
}
else if (result instanceof Flux) {
return Flux.from((Flux<?>) result).collectList();
else if (result instanceof Flux<?>) {
return ((Flux<?>) result).collectList();
}
else if (result instanceof CompletableFuture<?>) {
return Mono.fromFuture((CompletableFuture<?>) result);
}
else {
return Mono.justOrEmpty(result);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -26,6 +26,7 @@
import graphql.schema.DataFetchingEnvironmentImpl;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import reactor.core.publisher.Mono;

import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.graphql.data.GraphQlArgumentBinder;
Expand All @@ -35,6 +36,8 @@
import org.springframework.graphql.data.method.annotation.Argument;
import org.springframework.graphql.data.method.annotation.QueryMapping;
import org.springframework.lang.Nullable;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.User;
import org.springframework.util.ClassUtils;

import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -86,6 +89,23 @@ void callableReturnValue() throws Exception {
assertThat(future.get()).isEqualTo("A");
}

@Test
void completableFutureReturnValue() {

HandlerMethodArgumentResolverComposite resolvers = new HandlerMethodArgumentResolverComposite();
resolvers.addResolver(new AuthenticationPrincipalArgumentResolver((beanName, context) -> null));
resolvers.addResolver(new ArgumentMethodArgumentResolver(new GraphQlArgumentBinder()));

DataFetcherHandlerMethod handlerMethod = new DataFetcherHandlerMethod(
handlerMethodFor(new TestController(), "handleAndReturnFuture"), resolvers,
null, null, false);

Object result = handlerMethod.invoke(DataFetchingEnvironmentImpl.newDataFetchingEnvironment().build());

assertThat(result).isInstanceOf(Mono.class);
assertThat(((Mono<String>) result).block()).isEqualTo("B");
}

private static HandlerMethod handlerMethodFor(Object controller, String methodName) {
Method method = ClassUtils.getMethod(controller.getClass(), methodName, (Class<?>[]) null);
return new HandlerMethod(controller, method);
Expand All @@ -112,6 +132,10 @@ public Callable<String> handleAndReturnCallable() {
return () -> "A";
}

public CompletableFuture<String> handleAndReturnFuture(@AuthenticationPrincipal User user) {
return CompletableFuture.completedFuture("B");
}

}

}

0 comments on commit 9066c40

Please sign in to comment.