Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Request is not send without block()

I want to use this webflux client code to send POST requests with reply and without reply. I tried this code implementation:

public class RestClientBuilder {
    private String token;
    private String username;
    private String password;
    private URL gatewayUrl;
    private SslContextBuilder sslContextBuilder;

    public static RestClientBuilder builder() {
        return new RestClientBuilder();
    }

    public RestClientBuilder token(String token) {
        this.token = validateAndTrim(token, "Token");
        return this;
    }

    public RestClientBuilder usernamePassword(String username, String password) {
        this.username = validateAndTrim(username, "Username");
        this.password = validateAndTrim(password, "Password");
        return this;
    }

    private String validateAndTrim(String value, final String parameter) {
        if (value == null || value.trim().isEmpty()) {
            throw new IllegalArgumentException(parameter + " is empty");
        }
        return value.trim();
    }

    public RestClientBuilder gatewayUrl(String gatewayUrl) {
        String urlSt = validateAndTrim(gatewayUrl, "Gateway URL");
        try {
            this.gatewayUrl = new URL(urlSt);
        } catch (MalformedURLException e) {
            throw new IllegalArgumentException("Malformed URL: " + urlSt, e);
        }
        return this;
    }

    public RestClientBuilder truststore(File truststoreFile) {
        getSslContextBuilder().trustManager(truststoreFile);
        return this;
    }

    public RestClientBuilder sslCertificate(File keyCertChainFile, File keyFile, String keyPassword) {
        getSslContextBuilder().keyManager(keyCertChainFile, keyFile, keyPassword);
        return this;
    }

    public RestClient build() throws SSLException {
        SslContext sslContext = sslContextBuilder != null ? sslContextBuilder.build() : null;
        return new RestClient(gatewayUrl.toString(), token, username, password, sslContext);
    }

    private SslContextBuilder getSslContextBuilder() {
        if (sslContextBuilder == null) {
            sslContextBuilder = SslContextBuilder.forClient();
        }
        return sslContextBuilder;
    }

}

Implementation of the rest client:

public class RestClient {

    private WebClient client;
    private String gatewayUrl;

    public RestClient(String gatewayUrl, String token, String username, String password, SslContext sslContext) {
        this.gatewayUrl = gatewayUrl;
        WebClient.Builder builder = WebClient.builder().baseUrl(gatewayUrl);
        if (sslContext != null) {
            HttpClient httpClient = HttpClient.create().secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
            ClientHttpConnector httpConnector = new ReactorClientHttpConnector(httpClient);
            builder.clientConnector(httpConnector);
        }
        if (username != null && password != null) {
            builder.filter(basicAuthentication(username, password));
        }
        client = builder.build();
    }

    public Mono<Void> executeOnly(ReportRequest transaction) {
        Mono<ReportRequest> transactionMono = Mono.just(transaction);
        return client.post().uri(gatewayUrl)
                .accept(MediaType.APPLICATION_XML)
                .contentType(MediaType.APPLICATION_XML)
                .body(transactionMono, ReportRequest.class)
                .retrieve()
                .bodyToMono(Void.class);
    }
}

Make remote calls:

public class ReportingProcessor {

    private String URL2 = "......";

    public void collectEnvironmentData() throws JAXBException {

        ReportRequest report = new ReportRequest();
        report.setVersion("1.0");

        RestClient client = null;
        try {
            client = RestClientBuilder.builder()
                    .gatewayUrl(URL2)
//                .token(contract.getTerminal_token())
//                  .usernamePassword("user", "password")
//                .truststore(new File("server.pem"))
//                .sslCertificate(new File("client.pem"), new File("clientKey.p8"), "secret")
                    .build();
        } catch (SSLException e) {
            e.printStackTrace();
        }

        Mono<Void> result = client.executeOnly(report);
        Void response = result.block();

    }

When I remove Void response = result.block(); the request is not send. I Can't find why. Can you give me some advice how to make the client code working without using block().

like image 989
Peter Penzov Avatar asked Mar 03 '23 07:03

Peter Penzov


2 Answers

Whenever you work with Spring-webflux you have to keep one thing in mind. i.e You don't have to break your chain. because it is necessary to, someone should call subscribe on your chain. as it works on RXJava specification.

if you break the chain then you have to call block() which not recommended.

you have to modify your code in the below manner.

Let's Consider you have a handler which is making a call to your collectEnvironmentData() method and your method is making a call to remote service.

public  Mono<ServerResponse> handelerMethod(ServerRequest request){
  return collectEnvironmentData().flatMap(aVoid -> ServerResponse.ok().build());
}

your method should be modified to

public Mono<Void> collectEnvironmentData() throws JAXBException {

ReportRequest report = new ReportRequest();
report.setVersion("1.0");

RestClient client = null;
try {
    client = RestClientBuilder.builder()
            .gatewayUrl(URL2)
//                .token(contract.getTerminal_token())
//                  .usernamePassword("user", "password")
//                .truststore(new File("server.pem"))
//                .sslCertificate(new File("client.pem"), new File("clientKey.p8"), 
//"secret").build();
} catch (SSLException e) {
    e.printStackTrace();
}

return client.executeOnly(report);
}

Change your implementation in the above manner, hope it will work.

like image 136
Pratik Bhajankar Avatar answered Mar 12 '23 08:03

Pratik Bhajankar


How I would implement your method is:

public Mono<Void> executeOnly(ReportRequest transaction) {
    Mono<ReportRequest> transactionMono = Mono.just(transaction);
    return client.post().uri(gatewayUrl)
        .accept(MediaType.APPLICATION_XML)
        .contentType(MediaType.APPLICATION_XML)
        .body(transaction, ReportRequest.class)
        .exchange()
        .then();
}

And then I would use it as follows:

client.executeOnly(report).subscribe()

like image 28
Rozart Avatar answered Mar 12 '23 09:03

Rozart