0

I want to set up a fallback when my program works if the first service is unavailable.

On the second service, I use WebClient which accesses the first service and receives data from it.

I made two options but they do not work for me.

If both services are alive, then everything works well. If the first service is unavailable, then when I try to send a request via WebClient, nothing happens, I see a blank screen in the browser.

1) The first option:

@Service
public class WebClientService {

    private static final String API_MIME_TYPE = "application/json";
    private static final String API_BASE_URL = "http://localhost:8081";
    private static final String USER_AGENT = "User Service";
    private static final Logger logger = LoggerFactory.getLogger(WebClientService.class);

    private WebClient webClient;

    public WebClientService() {
        this.webClient = WebClient.builder()
                .baseUrl(API_BASE_URL)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, API_MIME_TYPE)
                .defaultHeader(HttpHeaders.USER_AGENT, USER_AGENT)
                .filter(WebClientService.errorHandlingFilter()) 
                .build();
    }


     public Flux<Bucket> getDataByWebClient() {
        return webClient
                .get()
                .uri("/getAll")
                .exchange()
                .flatMapMany(clientResponse -> clientResponse.bodyToFlux(Bucket.class));
    }

    public static ExchangeFilterFunction errorHandlingFilter() {
        return ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
            if(clientResponse.statusCode()!=null && (clientResponse.statusCode().is5xxServerError() || clientResponse.statusCode().is4xxClientError()) ) {
                return clientResponse.bodyToMono(String.class)
                        .flatMap(errorBody -> {
                            return Mono.error(new MyCustomServerException());
                        });
            }else {
                return Mono.just(clientResponse);
            }
        });
    }

}

Class MyCustomServerException

public class MyCustomServerException extends Throwable {

    public String getAllEmployeesList() {
        return "Server error";
    }

    public MyCustomServerException() {
        getAllEmployeesList();
    }

}

2) The second option:

@Service
public class WebClientService {

    private static final String API_MIME_TYPE = "application/json";
    private static final String API_BASE_URL = "http://localhost:8081";
    private static final String USER_AGENT = "User Service";
    private static final Logger logger = LoggerFactory.getLogger(WebClientService.class);

    private WebClient webClient;

    public WebClientService() {
        this.webClient = WebClient.builder()
                .baseUrl(API_BASE_URL)
                .defaultHeader(HttpHeaders.CONTENT_TYPE, API_MIME_TYPE)
                .defaultHeader(HttpHeaders.USER_AGENT, USER_AGENT)
                .build();
    }

    public Flux<Bucket> getDataByWebClient() {
        return webClient
                .get()
                .uri("/stream/buckets/delay")
                .exchange()
                .flatMapMany(clientResponse -> clientResponse.bodyToFlux(Bucket.class));
    }


    public Flux<Bucket> getDataByWebClient() {
        return webClient
                .get()
                .uri("/getAll")
                .retrieve()
                .onStatus(HttpStatus::is4xxClientError, response -> {
                    System.out.println("4xx eror");
                    return Mono.error(new RuntimeException("4xx"));
                })
                .onStatus(HttpStatus::is5xxServerError, response -> {
                    System.out.println("5xx eror");
                    return Mono.error(new RuntimeException("5xx"));
                })

                .onStatus(HttpStatus::isError, clientResponse -> {
                    System.out.println("eror");
                    return Mono.error(new MyCustomServerException());
                })
                .bodyToFlux(Bucket.class);
    }

}

Why is this not working? Can anyone tell me?

I want the browser to display the message "Server error" from my class with an error.

Thanks!

Kirill Sereda
  • 469
  • 1
  • 10
  • 25
  • There is a browser. And there is a service using WebClient. What is there in between? – JB Nizet Aug 23 '19 at 13:45
  • @JBNizet I have firt service and second service. I'm using Spring WebFlux dependency. When I call method on second service which WebClient it will call method on first service and I will get data from DB (first service communicate with DB). Second service with WebClient communicate with first service. – Kirill Sereda Aug 23 '19 at 13:48
  • I understand that. You already said that in your post. But your question is: "why do I see a blank page in my browser?". How could we possibly answer that question if you don't post the code that is supposed to generate a non-blank page? – JB Nizet Aug 23 '19 at 13:49
  • @JBNizet I'm sorry for my boring, but I used MyCustomServerException. But maybe I'm wrong – Kirill Sereda Aug 23 '19 at 14:00
  • You don't seem to undertand. Let me paraphrase your question: *Here's some code I use in my service layer: `throw new MyCustomException()`. But my web browser page is blank. Why?* Are you able to answer that question? – JB Nizet Aug 23 '19 at 14:02
  • @JBNizet Yes, maybe I didn’t put it that way. I would like to receive some message for the user if the first service is unavailable. Those. instead of an error or a blank page, I would like to get something like: "Sorry, the service is temporarily unavailable." – Kirill Sereda Aug 23 '19 at 14:08
  • Well, in the presentation layer of your app, which we know nothing about, make sure to generate and display such an error message then. That won't happen all by itself. And if you already tried to do that, and think such a message should be displayed, then post the code. – JB Nizet Aug 23 '19 at 14:12

0 Answers0