Как выполнить вызовы Java к GraphQL в контексте Spring Boot + GraphQL Java Tools? - PullRequest
1 голос
/ 01 октября 2019

В приложении Spring Boot у нас уже есть полнофункциональная конечная точка GraphQL, обслуживающая файлы .graphqls с помощью GraphQL Java Tools (мы включили зависимость graphql-spring-boot-starter) и обрабатывающая разрешение данных через наш базовый класс Queryреализация GraphQLQueryResolver и последующих GraphQLResolver.

Для бизнес-целей нам необходимо заново создать стандартные конечные точки API REST, поэтому я удивляюсь, почему бы просто не вызывать GraphQL (вместо-произвести «вручную» разрешение данных еще раз)? И поскольку он находится в одном и том же бэкэнд-приложении, нет необходимости делать HTTP или сервлет (ForwardRequest) вызовы, просто вызовите некоторые API в Java. Дело в том, что я не знаю, как поступить.

Я читал этот пример, но он с базовым GraphQL Java (не Tools): https://www.graphql -java.com / documents / v9 / execute/

Я знаю, что это возможно, потому что нам разрешено делать это в тестах: https://github.com/graphql-java-kickstart/graphql-spring-boot/blob/master/example-graphql-tools/src/test/java/com/graphql/sample/boot/GraphQLToolsSampleApplicationTest.java

Но как это сделать в обычном коде? Нет такой вещи как GraphQLTemplate.

. Я также пытался искать примеры по адресу:

, но не нашел ничего, что соответствовало бы нашим потребностям.

Больше ничего не нашел в документации:

Что я пропустил? В идеале я хочу ввести немного GraphQLSomething, например:

@RestController
@RequestMapping(path = "api")
public class CompanyController {

    @Autowired
    private GraphQLSomething graphQLSomething;

    @GetMapping("company/{id}")
    public ResponseEntity<?> societe(@PathVariable @NotNull Integer id) {
        GraphQLSomethingResult result = GraphQLSomething.query("company(id: $id) { id name andsoone }", "{ \"id\": 123456 }").execute(); // not really sure of the GraphQL syntax here, but it'll need some tests...
        return result.getDataOrElse();
    }

}

1 Ответ

0 голосов
/ 09 октября 2019

Наконец-то нашёл, как сделать то, что хотел:

import java.util.Map;
import java.util.Optional;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Positive;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.google.common.collect.ImmutableMap;

import graphql.ExecutionResult;
import graphql.servlet.core.GraphQLQueryInvoker;
import graphql.servlet.core.internal.GraphQLRequest;
import graphql.servlet.input.GraphQLInvocationInputFactory;
import graphql.servlet.input.GraphQLSingleInvocationInput;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Validated
@RestController
@RequestMapping(path = "api")
public class CompanyController {

    @Autowired
    private GraphQLInvocationInputFactory invocationInputFactory;

    @Autowired
    private GraphQLQueryInvoker queryInvoker;

    @GetMapping("company/{id}")
    public ResponseEntity<?> societe(@PathVariable @NotNull Integer id) {
        String query = "query ($id: Int!) { company(id: $id) { id name andsoon } }";
        /*
         * ImmutableMap is a Guava class; you can build the map (e.g. a HashMap) on your
         * own, or simply Map.to(..) in Java 9, or even @PathVariable Map<String,
         * Object> variables as the method's parameter instead (but you'll miss the
         * validation).
         */
        Map<String, Object> variables = ImmutableMap.of("id", id);

        GraphQLRequest request = new GraphQLRequest(query, variables, null);
        GraphQLSingleInvocationInput invocationInput = invocationInputFactory.create(request);
        ExecutionResult result = queryInvoker.query(invocationInput);

        /*
         * Of course result.getData() can be null here - see also result.isDataPresent()
         * - but data/error handling's left to you
         */
        Optional<Object> company = Optional.ofNullable(result.getData().get("company"));
        return ResponseEntity.of(company);
    }

}
...