Design de aplicativos

Processamento de consultas GraphQL com Java, Spring Boot e NoSQL

Nos últimos meses, tenho aprendido sobre o GraphQL e como usá-lo como uma alternativa ao desenvolvimento de APIs RESTful. Até agora, o foco estava em GraphQL e Golang bem como GraphQL e Node.js. Talvez eu tenha espremido tudo o que podia nessas duas linguagens de desenvolvimento, então decidi mudar de marcha e tentar a sorte com um pouco de Java.

Neste tutorial, veremos como começar a trabalhar rapidamente com o GraphQL usando Java e a popular estrutura Spring Boot.

Antes de entrarmos no assunto, quero dar crédito onde o crédito é merecido. Prithviraj Pawar escreveu um excelente artigo intitulado, Como colocar seu servidor Java GraphQL em funcionamento em pouco tempoque me deu muitas ideias, embora houvesse coisas a desejar, como um banco de dados em vez de dados simulados. Recomendo que você leia o artigo dele depois de ler o meu.

Os requisitos

Existem alguns pré-requisitos que devem ser atendidos antes de entrarmos no GraphQL e no lado do desenvolvimento.

Vamos supor que você já tenha o Couchbase instalado, configurado e em execução. Qualquer versão posterior ao Couchbase Server 5.0 será suficiente, pois usaremos apenas os recursos básicos.

Também vamos supor que você tenha baixado um projeto básico do Spring Boot. O projeto Site do Spring Boot tem um ótimo gerador que permite que você defina as dependências. Se quiser manter a coerência com meu guia, você precisará criar um projeto Gradle em vez de Maven.

Definição das dependências do projeto Gradle

Quando você tiver um modelo do Spring Boot em mãos, ele provavelmente estará bem vazio. Precisamos incluir as dependências que planejamos usar em nossa configuração do Gradle.

Abra o arquivo build.gradle e inclua o seguinte:

Usaremos o Spring Boot para atender ao nosso endpoint GraphQL, o Couchbase Java SDK para interações com nosso banco de dados e o plug-in GraphQL para o processamento de consultas.

Inicialização da API Java com pontos de extremidade RESTful

Com as dependências estabelecidas, podemos começar a desenvolver nossa API. Embora estejamos usando o GraphQL como um substituto para todas as coisas comuns da API RESTful, isso não significa que o REST esteja completamente fora da equação. Ainda precisamos de um endpoint para enviar nossas consultas GraphQL.

Dependendo do nome que você deu ao seu projeto, pacote, etc., abra o arquivo que contém seu principal e incluir o seguinte:

Lembre-se de que seu pacote e nome de classe podem não corresponder aos meus. Preencha as lacunas onde for apropriado.

Você notará que temos dois endpoints, sendo que um é totalmente opcional. Eu criei o rootEndpoint como uma forma de testar se a minha API RESTful estava de fato funcionando. A graphql é o ponto de extremidade em que passaremos nosso tempo. Ele espera uma solicitação POST, bem como um corpo de solicitação. O corpo da solicitação eventualmente será uma consulta real do GraphQL, mas, por enquanto, podemos deixá-lo como está.

Projetando um documento de esquema do GraphQL

Até agora, fizemos apenas alguns trabalhos básicos de preparação do Spring Boot e nada realmente relacionado ao GraphQL. Para que o GraphQL seja possível, precisamos conhecer um esquema definido que explique as consultas disponíveis, bem como os tipos de dados com os quais estamos trabalhando. Há várias maneiras de fazer isso, mas vamos nos concentrar em um documento de esquema.

Dentro do recursos de seu projeto, inclua um arquivo schema.graphql que contém o seguinte:

Caso não seja óbvio, estaremos trabalhando com dados de Pokémon. No arquivo acima, definimos as consultas que estão disponíveis e os dois tipos de dados disponíveis.

Há uma variedade de jogos de Pokémon no mercado e há diferentes Pokémon em cada um dos jogos, daí a relação que definimos. Se você for um verdadeiro fã de Pokémon, saberá que há um pouco mais do que isso, mas para este exemplo é o suficiente.

Desenvolvimento da lógica de busca para o banco de dados NoSQL do Couchbase

Com o esquema definido, precisamos criar uma lógica de banco de dados a ser executada quando uma consulta for realizada, e essa lógica de banco de dados deve retornar resultados que correspondam a cada um dos dois tipos de dados.

Para facilitar um pouco a vida na manutenção do projeto, vamos criar um arquivo separado para gerenciar o banco de dados. Em seu pacote, crie um arquivo Banco de dados.java que contém o seguinte:

Em sua maior parte, o conjunto de funções acima deve parecer familiar, pois as definimos de certa forma para corresponder ao que tínhamos em nosso arquivo de esquema GraphQL.

Alguns pontos a serem observados antes de começarmos a preencher cada uma das funções:

  1. O bucket será definido em nosso arquivo de projeto principal logo após definirmos nossa lógica.
  2. O GraphQL espera um determinado tipo de resposta, portanto, o extractResultOrThrow que criamos.

Com isso em mente, vamos começar criando a função wrapper. A função extractResultOrThrow será usada somente em consultas N1QL e terá a seguinte aparência:

Basicamente, estamos apenas percorrendo um conjunto de resultados N1QL e criando um Lista de Mapa dele.

Supondo que tenhamos dados de jogos em nosso banco de dados, podemos consultar esses dados no getGamesData função:

Usando o N1QL, podemos consultar os documentos que correspondem ao tipo de jogo e processar os resultados com nossa função de wrapper. Se você realmente quiser ser rigoroso, em vez de usar um asterisco curinga, poderá definir as propriedades que correspondem ao seu esquema.

A próxima função, getPokemonDataO recurso de consulta de dados do Pokémon nos permitirá consultar nossos dados do Pokémon de forma semelhante à que fizemos com os dados do jogo.

Você notará que não fizemos nada de novo além de alterar o tipo propriedade. É aqui que as coisas podem ficar interessantes. Temos um relacionamento de dados para Pokémon em relação aos dados do jogo. Podemos buscá-la em nossa consulta atual ou dividi-la para que seja mais modular e potencialmente mais leve. Vamos optar pela opção modular e leve.

Isso nos leva ao nosso getGameData função:

Há duas coisas acontecendo na função acima, nenhuma das quais usa N1QL.

Em nosso esquema, definimos uma consulta baseada em argumentos para os dados do jogo, bem como um relacionamento de dados nos dados do Pokémon. Vamos acomodar esses dois cenários na mesma função.

Usando o environment.getSource() podemos ver se há algum dado principal que acompanha a solicitação. Um exemplo desses dados principais pode ser quando consultamos dados sobre Pokémon. O jogo refere-se ao campo getGameData enquanto os outros dados, como nome, peso ou outros, referem-se aos dados principais. No banco de dados, as informações do jogo são armazenadas como um ID, portanto, depois de extraí-las dos dados principais, podemos fazer uma pesquisa dos dados do jogo.

O outro cenário é se passarmos um argumento que represente um ID de jogo.

Ambos são válidos e fazem coisas diferentes. No final, queremos apenas um único resultado em vez de uma matriz de resultados.

Conexão do aplicativo para o processamento bem-sucedido do GraphQL

Agora estamos na reta final. Temos nossa API e nossa lógica de banco de dados implementadas. A etapa final é conectar o esquema GraphQL à lógica do banco de dados e observar os resultados em toda a sua glória.

Lembra que, na etapa anterior, mencionei a configuração das informações do nosso bucket? Vamos cuidar disso primeiro. Abra a seção application.properties encontrado no arquivo recursos diretório. Inclua o seguinte:

As informações do meu banco de dados são apenas um exemplo. Certifique-se de substituí-las pelas informações que você está usando para sua instância do Couchbase.

De volta ao seu arquivo de projeto principal, podemos mapear os valores e nos conectar à nossa instância:

Observe que criamos dois Feijão e usou as informações do nosso arquivo de propriedades. Assim, estamos conectados ao Couchbase.

A próxima etapa é inicializar nosso esquema GraphQL. Há várias maneiras de fazer isso, mas achei mais fácil usar a anotação do Spring Boot para quando o aplicativo for iniciado:

O inicial será chamada quando o aplicativo for iniciado. Ela carregará nosso arquivo de esquema do diretório recursos e definir a fiação. Por exemplo, sabemos que pokemons, jogose game(id: String) são todos os tipos de consultas. Cada uma é mapeada para a função apropriada do banco de dados e o bucket aberto é passado. Em seguida, estabelecemos um mapeamento de jogo para o Pokémon tipo. Estamos mais ou menos definindo como os campos e as consultas estão vinculados à interação com o banco de dados.

Depois de criar o esquema, podemos vinculá-lo à nossa variável de classe. Com o esquema criado, podemos finalizar nosso ponto de extremidade GraphQL RESTful:

Em nosso endpoint, pegamos a string de consulta que foi passada com a solicitação e a executamos com nosso esquema construído. O resultado será o que o cliente solicitou na consulta.

Então, qual é a aparência de uma consulta? Veja, por exemplo, o seguinte:

A consulta acima provavelmente não é algo que alguém precise executar, mas você poderia fazê-lo se quisesse. No exemplo acima, estamos consultando todos os dados de Pokémon e o jogo do qual eles fazem parte. Também estamos consultando todos os jogos, bem como um jogo específico. Todas as três partes da consulta não estão relacionadas, mas existem na mesma consulta.

Como um fato interessante, no pokemons se optarmos por não consultar os dados do jogo, a função do banco de dados nunca será chamada. O GraphQL só executará funções quando elas forem necessárias.

Conclusão

Você acabou de ver como criar um aplicativo GraphQL usando Spring Boot, Java e Couchbase Server como banco de dados NoSQL. Como você viu na minha consulta de exemplo, conseguimos consultar muitos dados diferentes e não relacionados em uma única solicitação, algo que teria exigido várias em uma API RESTful.

Para obter mais informações sobre como usar o Java SDK com o Couchbase, consulte a seção Portal do desenvolvedor do Couchbase.

Compartilhe este artigo
Receba atualizações do blog do Couchbase em sua caixa de entrada
Esse campo é obrigatório.

Autor

Postado por Nic Raboy

Nic Raboy é um defensor das modernas tecnologias de desenvolvimento móvel e da Web. Ele tem experiência em Java, JavaScript, Golang e uma variedade de estruturas, como Angular, NativeScript e Apache Cordova. Nic escreve sobre suas experiências de desenvolvimento relacionadas a tornar o desenvolvimento móvel e da Web mais fácil de entender.

Deixe um comentário

Pronto para começar a usar o Couchbase Capella?

Iniciar a construção

Confira nosso portal do desenvolvedor para explorar o NoSQL, procurar recursos e começar a usar os tutoriais.

Use o Capella gratuitamente

Comece a trabalhar com o Couchbase em apenas alguns cliques. O Capella DBaaS é a maneira mais fácil e rápida de começar.

Entre em contato

Deseja saber mais sobre as ofertas do Couchbase? Deixe-nos ajudar.