5
respostas

Consumir API Graphql usando Spring Boot

Boa tarde!
É possível consumir uma API externa feita em Graphql utilizando Spring?
Se sim poderia mostrar um exemplo?
5 respostas

Tentei utlizar o RestTemplate mas é retornado null nos campos, como seria a implementação com webclient?

@Service
public class ConsumeGraphqlService {

    @Autowired
    private WebClient webClient;

    String url = "https://rickandmortyapi.com/graphql";
    // site usado para formatar a query em json https://jsonlint.com/
    String query = "{\n" + "    \"query\": \"query { episodesByIds(ids: [1, 2]) { name  characters {   name  } }}\"\n"
            + "}";



    public ResponseEntity<FilmeDto> consumirApi(){

        RestTemplate restTemplate = new RestTemplate();
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-type", "application/json");

        ResponseEntity<FilmeDto> response = restTemplate.postForEntity(url, new HttpEntity<>(query,headers),FilmeDto.class);
        return response;

    }
@RestController
@RequestMapping("/api/graphql")
public class ConsumeGraphqlController {

    @Autowired
    private ConsumeGraphqlService service;


    @GetMapping("/chamarapi")
    public  ResponseEntity<FilmeDto> chamarApi() {

        ResponseEntity<FilmeDto> filmes = service.consumirApi();


        return filmes;

    }

Oi Marcos,

Você tem a depéndencia webflux do Spring Boot no seu projeto?

Desse jeito que você fez deveria funcionar. Talvez o problema seja no seu DTO, que pode não estar refletindo os dados no formato que são devolvidos pela API.

Posta aqui o código da sua classe DTO.

Oi Rodrigo, Segue o pom.xml e o DTO que fiz no projeto

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>br.com.consume.graphql</groupId>
    <artifactId>consume-graphql</artifactId>
    <version>1</version>
    <name>consume-graphql</name>
    <description>consume-graphql</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

CharactersDto

import lombok.Data;

@Data
public class CharactersDto {
    private String name;

}

FilmeDto

@Data
public class FilmeDto {

    private String name;
    @JsonAlias("characters")
    private CharactersDto charactersDto;



}

Oi Marcos,

Eu fiz uma chamada para essa API Graphql e ela devolve um json no seguinte formato:

{
   "data":{
      "episodesByIds":[
         {
            "name":"Pilot",
            "characters":[
               {
                  "name":"Rick Sanchez"
               },
               {
                  "name":"Morty Smith"
               },
               {
                  "name":"Bepisian"
               },
               {
                  "name":"Beth Smith"
               },
               {
                  "name":"Canklanker Thom"
               },
               {
                  "name":"Davin"
               },
               {
                  "name":"Frank Palicky"
               },
               {
                  "name":"Glenn"
               },
               {
                  "name":"Hookah Alien"
               },
               {
                  "name":"Jerry Smith"
               },
               {
                  "name":"Jessica"
               },
               {
                  "name":"Jessica's Friend"
               },
               {
                  "name":"Mr. Goldenfold"
               },
               {
                  "name":"Mrs. Sanchez"
               },
               {
                  "name":"Principal Vagina"
               },
               {
                  "name":"Summer Smith"
               },
               {
                  "name":"Davin"
               },
               {
                  "name":"Greebybobe"
               },
               {
                  "name":"Pripudlian"
               }
            ]
         },
         {
            "name":"Lawnmower Dog",
            "characters":[
               {
                  "name":"Rick Sanchez"
               },
               {
                  "name":"Morty Smith"
               },
               {
                  "name":"Beth Smith"
               },
               {
                  "name":"Bill"
               },
               {
                  "name":"Centaur"
               },
               {
                  "name":"Creepy Little Girl"
               },
               {
                  "name":"Jerry Smith"
               },
               {
                  "name":"Melissa"
               },
               {
                  "name":"Mr. Goldenfold"
               },
               {
                  "name":"Mrs. Pancakes"
               },
               {
                  "name":"Scary Brandon"
               },
               {
                  "name":"Scary Glenn"
               },
               {
                  "name":"Scary Terry"
               },
               {
                  "name":"Snuffles (Snowball)"
               },
               {
                  "name":"Summer Smith"
               },
               {
                  "name":"Scary Teacher"
               },
               {
                  "name":"Fido"
               },
               {
                  "name":"Accountant dog"
               },
               {
                  "name":"Trunkphobic suspenders guy"
               }
            ]
         }
      ]
   }
}

Então o retorno da chamada ao método restTemplate.postForEntity não deve ser um FilmeDto e sim outro DTO contendo um atributo chamado data, que seria outro DTO, e dentro desse outro teria um atributo chamado episodesByIds sendo que esse sim seria do tipo List<FilmeDto>.

Ou seja, deve seguir a mesma hierarquia dos dados que forem devolvidos pela API.

Oi Rodrigo, obrigado pelo retorno, vou ajustar a API e testar e retorno no forum.