/** * Executes the graphql query using the provided input object builder * <p> * This will return a promise (aka {@link CompletableFuture}) to provide a {@link ExecutionResult} * which is the result of executing the provided query. * * @param executionInputBuilder {@link ExecutionInput.Builder} * * @return a promise to an {@link ExecutionResult} which can include errors */ public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput.Builder executionInputBuilder) { return executeAsync(executionInputBuilder.build()); }
/** * Executes the graphql query using the provided input object * * @param executionInput {@link ExecutionInput} * * @return an {@link ExecutionResult} which can include errors */ public ExecutionResult execute(ExecutionInput executionInput) { try { return executeAsync(executionInput).join(); } catch (CompletionException e) { if (e.getCause() instanceof RuntimeException) { throw (RuntimeException) e.getCause(); } else { throw e; } } }
/** * Executes the graphql query using the provided input object builder * <p> * This will return a promise (aka {@link CompletableFuture}) to provide a {@link ExecutionResult} * which is the result of executing the provided query. * <p> * This allows a lambda style like : * <pre> * {@code * ExecutionResult result = graphql.execute(input -> input.query("{hello}").root(startingObj).context(contextObj)); * } * </pre> * * @param builderFunction a function that is given a {@link ExecutionInput.Builder} * * @return a promise to an {@link ExecutionResult} which can include errors */ public CompletableFuture<ExecutionResult> executeAsync(UnaryOperator<ExecutionInput.Builder> builderFunction) { return executeAsync(builderFunction.apply(ExecutionInput.newExecutionInput()).build()); }
private void equivalentSerialAndAsyncQueryExecution() throws Exception { //::FigureC ExecutionResult executionResult = graphQL.execute(executionInput); // the above is equivalent to the following code (in long hand) CompletableFuture<ExecutionResult> promise = graphQL.executeAsync(executionInput); ExecutionResult executionResult2 = promise.join(); //::/FigureC }
@SuppressWarnings({"Convert2MethodRef", "unused", "FutureReturnValueIgnored"}) private void simpleAsyncQueryExecution() throws Exception { //::FigureB GraphQL graphQL = buildSchema(); ExecutionInput executionInput = ExecutionInput.newExecutionInput().query("query { hero { name } }") .build(); CompletableFuture<ExecutionResult> promise = graphQL.executeAsync(executionInput); promise.thenAccept(executionResult -> { // here you might send back the results as JSON over HTTP encodeResultToJsonAndSendResponse(executionResult); }); promise.join(); //::/FigureB }
/** * Executes the graphql query using the provided input object builder * <p> * This will return a promise (aka {@link CompletableFuture}) to provide a {@link ExecutionResult} * which is the result of executing the provided query. * * @param executionInputBuilder {@link ExecutionInput.Builder} * * @return a promise to an {@link ExecutionResult} which can include errors */ public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput.Builder executionInputBuilder) { return executeAsync(executionInputBuilder.build()); }
/** * Executes the graphql query using the provided input object * * @param executionInput {@link ExecutionInput} * * @return an {@link ExecutionResult} which can include errors */ public ExecutionResult execute(ExecutionInput executionInput) { try { return executeAsync(executionInput).join(); } catch (CompletionException e) { if (e.getCause() instanceof RuntimeException) { throw (RuntimeException) e.getCause(); } else { throw e; } } }
/** * Executes the graphql query using the provided input object builder * <p> * This will return a promise (aka {@link CompletableFuture}) to provide a {@link ExecutionResult} * which is the result of executing the provided query. * <p> * This allows a lambda style like : * <pre> * {@code * ExecutionResult result = graphql.execute(input -> input.query("{hello}").root(startingObj).context(contextObj)); * } * </pre> * * @param builderFunction a function that is given a {@link ExecutionInput.Builder} * * @return a promise to an {@link ExecutionResult} which can include errors */ public CompletableFuture<ExecutionResult> executeAsync(UnaryOperator<ExecutionInput.Builder> builderFunction) { return executeAsync(builderFunction.apply(ExecutionInput.newExecutionInput()).build()); }
@Override public CompletableFuture<ExecutionResult> executeAsync(ExecutionInput executionInput) { return delegate.executeAsync(executionInput.transform(builder -> builder.context(new ContextWrapper(executionInput.getContext())))); }
@Test public void endpointIsAvailable() { String query = "{foo}"; ExecutionResultImpl executionResult = ExecutionResultImpl.newExecutionResult() .data("bar") .build(); CompletableFuture cf = CompletableFuture.completedFuture(executionResult); ArgumentCaptor<ExecutionInput> captor = ArgumentCaptor.forClass(ExecutionInput.class); Mockito.when(graphql.executeAsync(captor.capture())).thenReturn(cf); String body = this.restTemplate.getForObject("/graphql?query={query}", String.class, query); assertThat(body, is("{\"data\":\"bar\"}")); assertThat(captor.getValue().getQuery(), is(query)); }
@Test public void endpointIsAvailableWithDifferentUrl() { String query = "{foo}"; ExecutionResultImpl executionResult = ExecutionResultImpl.newExecutionResult() .data("bar") .build(); CompletableFuture cf = CompletableFuture.completedFuture(executionResult); ArgumentCaptor<ExecutionInput> captor = ArgumentCaptor.forClass(ExecutionInput.class); Mockito.when(graphql.executeAsync(captor.capture())).thenReturn(cf); String body = this.restTemplate.getForObject("/otherUrl/?query={query}", String.class, query); assertThat(body, is("{\"data\":\"bar\"}")); assertThat(captor.getValue().getQuery(), is(query)); }
@Override public CompletableFuture<ExecutionResult> invoke(GraphQLInvocationData invocationData, WebRequest webRequest) { ExecutionInput executionInput = ExecutionInput.newExecutionInput() .query(invocationData.getQuery()) .operationName(invocationData.getOperationName()) .variables(invocationData.getVariables()) .build(); return graphQL.executeAsync(executionInput); }
@Override public CompletableFuture<ExecutionResult> invoke(GraphQLInvocationData invocationData, WebRequest webRequest) { ExecutionInput executionInput = ExecutionInput.newExecutionInput() .query(invocationData.getQuery()) .operationName(invocationData.getOperationName()) .variables(invocationData.getVariables()) .build(); return graphQL.executeAsync(executionInput); }
@Test public void endpointIsAvailableWithDifferentUrl() { String query = "{foo}"; ExecutionResultImpl executionResult = ExecutionResultImpl.newExecutionResult() .data("bar") .build(); CompletableFuture cf = CompletableFuture.completedFuture(executionResult); ArgumentCaptor<ExecutionInput> captor = ArgumentCaptor.forClass(ExecutionInput.class); Mockito.when(graphql.executeAsync(captor.capture())).thenReturn(cf); this.webClient.get().uri("/otherUrl?query={query}", query).exchange().expectStatus().isOk() .expectBody(String.class).isEqualTo("{\"data\":\"bar\"}"); assertThat(captor.getValue().getQuery(), is(query)); }
@Override public Mono<ExecutionResult> invoke(GraphQLInvocationData invocationData, ServerWebExchange serverWebExchange) { ExecutionInput executionInput = ExecutionInput.newExecutionInput() .query(invocationData.getQuery()) .operationName(invocationData.getOperationName()) .variables(invocationData.getVariables()) .build(); return Mono.fromCompletionStage(graphQL.executeAsync(executionInput)); }
@Test public void endpointIsAvailable() { String query = "{foo}"; ExecutionResultImpl executionResult = ExecutionResultImpl.newExecutionResult() .data("bar") .build(); CompletableFuture cf = CompletableFuture.completedFuture(executionResult); ArgumentCaptor<ExecutionInput> captor = ArgumentCaptor.forClass(ExecutionInput.class); Mockito.when(graphql.executeAsync(captor.capture())).thenReturn(cf); this.webClient.get().uri("/graphql?query={query}", query).exchange().expectStatus().isOk() .expectBody(String.class).isEqualTo("{\"data\":\"bar\"}"); assertThat(captor.getValue().getQuery(), is(query)); }
@Override public Mono<ExecutionResult> invoke(GraphQLInvocationData invocationData, ServerWebExchange serverWebExchange) { ExecutionInput executionInput = ExecutionInput.newExecutionInput() .query(invocationData.getQuery()) .operationName(invocationData.getOperationName()) .variables(invocationData.getVariables()) .build(); return Mono.fromCompletionStage(graphQL.executeAsync(executionInput)); }
@Test public void testSimplePostRequest() throws Exception { Map<String, Object> request = new LinkedHashMap<>(); String query = "{foo}"; request.put("query", query); ExecutionResultImpl executionResult = ExecutionResultImpl.newExecutionResult() .data("bar") .build(); CompletableFuture cf = CompletableFuture.completedFuture(executionResult); ArgumentCaptor<ExecutionInput> captor = ArgumentCaptor.forClass(ExecutionInput.class); Mockito.when(graphql.executeAsync(captor.capture())).thenReturn(cf); client.post().uri("/graphql") .body(Mono.just(request), Map.class) .accept(MediaType.APPLICATION_JSON_UTF8) .exchange() .expectStatus().isOk() .expectBody() .jsonPath("data").isEqualTo("bar"); assertThat(captor.getAllValues().size(), is(1)); assertThat(captor.getValue().getQuery(), is(query)); }
@Test public void testSimpleGetRequest() throws Exception { String query = "{foo}"; String queryString = URLEncoder.encode(query, "UTF-8"); ExecutionResultImpl executionResult = ExecutionResultImpl.newExecutionResult() .data("bar") .build(); CompletableFuture cf = CompletableFuture.completedFuture(executionResult); ArgumentCaptor<ExecutionInput> captor = ArgumentCaptor.forClass(ExecutionInput.class); Mockito.when(graphql.executeAsync(captor.capture())).thenReturn(cf); client.get().uri(uriBuilder -> uriBuilder.path("/graphql") .queryParam("query", queryString) .build()) .accept(MediaType.APPLICATION_JSON_UTF8) .exchange() .expectStatus().isOk() .expectBody() .jsonPath("data").isEqualTo("bar"); assertThat(captor.getAllValues().size(), is(1)); assertThat(captor.getValue().getQuery(), is(query)); }
@Test public void testDifferentUrl() throws Exception { Map<String, Object> request = new LinkedHashMap<>(); String query = "{foo}"; request.put("query", query); ExecutionResultImpl executionResult = ExecutionResultImpl.newExecutionResult() .data("bar") .build(); CompletableFuture cf = CompletableFuture.completedFuture(executionResult); ArgumentCaptor<ExecutionInput> captor = ArgumentCaptor.forClass(ExecutionInput.class); Mockito.when(graphql.executeAsync(captor.capture())).thenReturn(cf); MvcResult mvcResult = this.mockMvc.perform(post("/otherUrl") .content(toJson(request)) .contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(status().isOk()) .andExpect(request().asyncStarted()) .andReturn(); this.mockMvc.perform(asyncDispatch(mvcResult)) .andDo(print()).andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8)) .andExpect(jsonPath("data", is("bar"))) .andReturn(); assertThat(captor.getAllValues().size(), is(1)); assertThat(captor.getValue().getQuery(), is(query)); }