Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Como converter o retorno de uma API não bloqueante?

Olá estou consumindo uma API externa usando webclient, consegui realizar o procedimento sem problemas, porém é retornado um objeto do tipo Mono(Mono

`public class AutorizacaoModelDto {

@JsonAlias("tokenAcesso")
private String tokenAcesso;

@JsonAlias("url")
private String urlAcesso;

private String id;

}@Configuration public class WebClientConfiguration {

@Value("${autorizacaoUrl.base_url}")
private String baseUrl;

@Bean
public WebClient createWebClient() {
    return WebClient.builder().baseUrl(baseUrl)
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .build();
}

}`

`public    Mono<AutorizacaoModelDto> recuperaToken() {

    String uri = "example.com.br"

    //System.out.println("#### uri: "+uri);

    return webClientConfiguration.createWebClient()
            .post()
             .uri(uri)
             .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
             .body(null)
             .retrieve()
             .bodyToMono(AutorizacaoModelDto.class);
}`

7 respostas

Oi Marcos,

Você pode utilizar o método block() para esperar a chamada concluir e devolver o objeto:

AutorizacaoModelDto dto = webClientConfiguration.createWebClient()
    .post()
    .uri(uri)
    .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
    .body(null)
    .retrieve()
    .bodyToMono(AutorizacaoModelDto.class)
    .block();

Bons estudos!

oi Rodrigo, neste caso ao utilizar o método block() é retornado a exceção "block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3",

oi, tentei usar outras alternativas para com o block() como o toFuture.block(), toProcessor().block(); e não tive sucesso, gostaria de pegar o retorno e passar para algum objeto ou varivel.

Oi Marcos,

Posta aqui o seu pom.xml e o código completo da chamada a API externa.

Oi Rodrigo, conforme solicitado seguem os dados:

Existe alguma forma de enviar os dados de acesso da API somente para você? Como esta API não é publica não posso publicar aqui os dados de conexão.

Pom.xml

<?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.6.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>br.com.mycompany.authorizationapi</groupId>
    <artifactId>authorizationapi</artifactId>
    <version>1</version>
    <name>authorizationapi</name>
    <description>testesteste</description>
    <properties>
        <java.version>1.8</java.version>
        <log4j2.version>2.17.0</log4j2.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>
    </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>

WebClient

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.web.reactive.function.client.WebClient;

@Configuration
public class WebClientConfiguration {

    @Value("${authorizationapi.base_url}")
    private String baseUrl;

    @Bean
    public WebClient createWebClient() {
        return WebClient.builder().baseUrl(baseUrl)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                .build();
    }

Service

public        Mono<AuthorizationModelDto> recuperaToken() {

            String uri = "?grant_type=" + grantType + "&" + "client_id=" + clientId + "&client_secret=" + clientSecret
                    + "&username=" + userName + "&password=" + password;

            Mono<AuthorizationModelDto> sxx = webClientConfiguration.createWebClient().post()
                                                         .uri(uri)
                                                         .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
                                                         .body(null)
                                                         .retrieve()
                                                         .bodyToMono(AuthorizationModelDto.class);


            sxx.subscribe(response -> retornarDados(response));

            return sxx;
        }

    private void retornarDados(AuthorizationModelDto teste) {

        System.out.println("########################################");
        System.out.println("ENTREI NO MÉTODO!"+teste.getAcessToken());
        System.out.println("ENTREI NO MÉTODO2!"+teste.getTokenType());
        System.out.println("ENTREI NO MÉTODO3!"+teste.getInstanceUrl());
        System.out.println("ENTREI NO MÉTODO4!"+teste.getIssuedAt());
        System.out.println("ENTREI NO MÉTODO5!"+teste.getSignature());
        System.out.println("ENTREI NO MÉTODO6!"+teste.getId());
        System.out.println("########################################");

    }

Controller

     @PostMapping
    public Mono<AuthorizationModelDto> retornarToken() {

        Mono<AuthorizationModelDto> retorno = authorizatorionService.recuperaToken1();

        System.out.println(retorno);

        return retorno;
    }
solução!

Oi Rodrigo,consegui resolver o problema da seguinte forma: Adicionei a dependência do spring web no projeto, o erro ao usar o método .block() . Porque estava somente com a dependência do webflux e dessa forma ele estava usando o servidor Netty, como o meu serviço não é bloqueante utilizando o servidor Tomcat foi suficiente e consigo utilizar o método block() normalmente para recuperar os valores que preciso.

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Ah sim, nem tinha reparado. Precisa dos dois mesmo por conta do servidor web.