DEV Community

Cover image for GraphQL no Quarkus
Luiz Leite Oliveira
Luiz Leite Oliveira

Posted on

GraphQL no Quarkus

Tudo que está nesse projeto pode ser encontrado no repositório GitHub.

Para a nossa poc o que fizemos foi primeiro pegar.

Intro ao projeto

Esse projeto já foi contextualizado no dev.to. Basicamente o que ele faz
é pegar usar o get da api encontrada em https://randomuser.me/api e aplica um GraphQL na resposta.

GRAPHQL On Quarkus

Dependências

Para utilizar o GraphQL neste projeto utilizamos uma dependência da Vert.x, documentação completa você pode encontrar
aqui para importar basta adicionar em seu pom.xml

    <dependency>
      <groupId>io.vertx</groupId>
      <artifactId>vertx-web-graphql</artifactId>
    </dependency>

Vamos para o código

Antes de usar o GraphQL precisamos modelar alguns DTO's para nossa modelagem:

public class Names {

    private String title;
    private String first;
    private String last;

//    Getters and Setters

}

Para esse modelo precisamos utilizaremos um Fetcher, que deve ficar da seguinte forma:

public class UserFetcher implements DataFetcher<List<User>> {

    private final UserClient userClient;

    public UserFetcher(UserClient userClient) {
        this.userClient = userClient;
    }


    private Results getResult() {
        return userClient.getUsers();
    }

    @Override
    public List<User> get(DataFetchingEnvironment environment) throws Exception {
        return getResult().getResults();
    }
}

Producer

Para pegar os resultados, vamos precisar também de uma classe producer como a seguir, é um pouco de boilerplate, vou tentar fazer uma
extensão de quarkus para reduzir essa e outras partes que são repetitivas, enquanto isso não acontece, a classe fica da seguinte forma:

 public class GraphQLProducer {

     private Logger LOGGER = LoggerFactory.getLogger(GraphQLProducer.class);

     @RestClient
     @Inject
     private UserClient userClient;

     @Produces
     public GraphQL setup() {

         LOGGER.info("Setting up GraphQL..");

         SchemaParser schemaParser = new SchemaParser();
         TypeDefinitionRegistry registry = schemaParser.parse(
             new InputStreamReader(
                 Objects.requireNonNull(Thread.currentThread().getContextClassLoader()
                     .getResourceAsStream("META-INF/resources/graphql.schema"))));

         SchemaGenerator schemaGenerator = new SchemaGenerator();
         GraphQLSchema graphQLSchema = schemaGenerator.makeExecutableSchema(registry, wirings());
         return GraphQL.newGraphQL(graphQLSchema).build();
     }

     private RuntimeWiring wirings() {

         LOGGER.info("Wiring queries..");

         return RuntimeWiring.newRuntimeWiring()
             .type("Query",
                 builder -> builder.dataFetcher("allUsers", new UserFetcher(userClient)))
             .build();
     }


 }

Na parte de getResourceAsStream() você coloca o schema de graphql que você desejar, no nosso caso ficou o META-INF/resources/graphql.schema

type Names {
  first: String
  last: String
}


type User {
  email: String
  name: Names
  gender: String
  phone: String
  cell: String
  nat: String
}

type Query {
  allUsers : [User]
}

Além disto, na parte de wirings() colocamos quem será o Fetcher que vai ser utilizado para allUsers que foi declarado dentro do graphql.schema

Finalizando temos que declarar a parte de Rotas (outra parte que é um pouco boilerplate que também pode entrar na extensão).

@ApplicationScoped
public class Routes {

    @Inject
    GraphQL graphQL;

    public void init(@Observes Router router) {

        boolean enableGraphiQL = true;

        router.route("/graphql")
            .handler(new GraphQLHandlerImpl(graphQL, new GraphQLHandlerOptions()));
        router.route("/graphiql/*").handler(
            GraphiQLHandler.create(new GraphiQLHandlerOptions().setEnabled(enableGraphiQL)));
    }

}

Foram declaradas duas rotas:

  1. /graphql → onde ficam os "endpoints" para acesso dos usuários
  2. /graphiql/* → onde fica a documentação para o que foi registrado.

## Concluindo
Resumindo tudo que fizemos não é muito complicado depois da primeira vez, mas falta muita documentação e várias vezes vi
lugares mostrando como se fosse meio que mágica, como se fizesse um import e já funciona. Depois de muitos testes funciona
bem, mas como já disse existem muitas partes que podem ser eliminadas por uma extensão mais completa.

Outra coisa que ficou muito obscuro e difícil são as headers como authorização não é muito simples de manipular e fazer alguma
validação com elas.

Com isso tudo não acho uma boa opção comparando com o que já tem em Spring Boot, para esse caso ainda não está maduro suficiente,
mas é claro que não está muito longe e, é fácil de ver como chegariam nesse ponto.

## Quer acompanhar um pouco mais?
Me siga nas plataformas._

GitHub: luizleite-hotmart

Twitter: luizleite_

Twitch: coffee_and_code

Linkedin: luizleiteoliveira

dev.to: luizleite_

Top comments (0)