Hello I’m trying to call API by using Webclient in spring boot.
But I’m having some issue.
Although the response I requested is a json response, the server gives me an xml response when server error occur.
So I am getting UnsupportedMediaTypeException error when server error occur.
Therefore I would like to make a buisness logic that can send me an email when UnsupportedMediaTypeException error occurs.
How can I handle UnsupportedMediaTypeException??
The code below is my api call code.
@Override public void run() { //여기서 API를 호출할거임 DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL); //UriBuilder를 생성하는 옵션을 설정하는 DefaultUriBuilderFactory 인스턴스 생성 factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); //encoding 모드 설정 HttpClient client = HttpClient.create() .responseTimeout(Duration.ofSeconds(60)); //http response timeout 설정을 60초로 설정함 WebClient wc = WebClient.builder() .uriBuilderFactory(factory) //위에서 만든 uri 인코딩 설정으로 uribuilder 설정을 함 .baseUrl(BASE_URL) //baseURI 설정하고 .clientConnector(new ReactorClientHttpConnector(client)) //위에서 만든 타임아웃 설정을 적용시키고 .build(); //빌드한다. result = new SweatherRootRes(); Mono<SweatherRootRes> response = wc.get() .uri(uriBuilder -> uriBuilder.path("/getVilageFcst") .queryParam("serviceKey", swr.getServiceKey()) .queryParam("numOfRows", swr.getNumOfRows()) .queryParam("pageNo", swr.getPageNo()) .queryParam("dataType", swr.getDataType()) .queryParam("base_date", swr.getBase_date()) .queryParam("base_time", swr.getBase_time()) .queryParam("nx", swr.getNx()) //지역정보 .queryParam("ny", swr.getNy()) //지역정보 .build()) //위 쿼리들로 uri 빌드를 하고 .retrieve() //http 요청하고 .onStatus(HttpStatus::is4xxClientError, error -> Mono.error(new RuntimeException("API not found"))) .onStatus(HttpStatus::is5xxServerError, error -> Mono.error(new RuntimeException("Server is not responding"))) .bodyToMono(SweatherRootRes.class);//Mono로 값을 받고 //여기서 type mismatch 되는 부분을 찾아야함 //비동기 방식으로 약간 콜백 메소드와 같은 역할을 하는것 같다.그래서 이부분은 api 연결이 성공했을때 들어오는 부분인것 같다. response.subscribe(res -> { result.setResponse(res.getResponse()); if(result.getResponse().getBody()!= null) { getTemp(result.getResponse().getBody().getItems()); logger.info(temp.toString()); callBack.completed(temp, null); cdl.countDown(); }else { logger.error("http reqeust has failed"); } }); }
Advertisement
Answer
I have solve this problem by using .doOnError()
and .onErrorReturn()
This is my code below
@Override public void run() { //여기서 API를 호출할거임 DefaultUriBuilderFactory factory = new DefaultUriBuilderFactory(BASE_URL); //UriBuilder를 생성하는 옵션을 설정하는 DefaultUriBuilderFactory 인스턴스 생성 factory.setEncodingMode(DefaultUriBuilderFactory.EncodingMode.VALUES_ONLY); //encoding 모드 설정 HttpClient client = HttpClient.create() .responseTimeout(Duration.ofSeconds(60)); //http response timeout 설정을 60초로 설정함 WebClient wc = WebClient.builder() .uriBuilderFactory(factory) //위에서 만든 uri 인코딩 설정으로 uribuilder 설정을 함 .baseUrl(BASE_URL) //baseURI 설정하고 .clientConnector(new ReactorClientHttpConnector(client)) //위에서 만든 타임아웃 설정을 적용시키고 .build(); //빌드한다. result = new SweatherRootRes(); //여기서 type mismatch 되는 부분을 찾아야함 Mono<SweatherRootRes> response = wc.get() .uri(uriBuilder -> uriBuilder.path("/getVilageFcst") .queryParam("serviceKey", 123) .queryParam("numOfRows", swr.getNumOfRows()) .queryParam("pageNo", swr.getPageNo()) .queryParam("dataType", swr.getDataType()) .queryParam("base_date", swr.getBase_date()) .queryParam("base_time", swr.getBase_time()) .queryParam("nx", swr.getNx()) //지역정보 .queryParam("ny", swr.getNy()) //지역정보 .build()) //위 쿼리들로 uri 빌드를 하고 .retrieve() //http 요청하고 .onStatus(HttpStatus::is4xxClientError, error -> Mono.error(new RuntimeException("API not found"))) .onStatus(HttpStatus::is5xxServerError, error -> Mono.error(new RuntimeException("Server is not responding"))) .bodyToMono(SweatherRootRes.class)//Mono로 값을 받고 .doOnError(e -> logger.error("ERROR OCCUR!")) //에러 발생했을때 알려줌 .onErrorReturn(new SweatherRootRes(true));//에러 발생하면 위 객체를 return 해줌 //비동기 방식으로 약간 콜백 메소드와 같은 역할을 하는것 같다.그래서 이부분은 api 연결이 성공했을때 들어오는 부분인것 같다. response.subscribe(res -> { if(res.isError()) { //에러라면 진입 callBack.failed(null, null); //callBack.failed() 호출 }else { result.setResponse(res.getResponse()); //response 값으로 설정 if(result.getResponse().getBody()!= null) { getTemp(result.getResponse().getBody().getItems()); //온도 구해서 세팅 logger.info(temp.toString()); callBack.completed(temp, null); //온도 값을 callBack에게 전달 cdl.countDown(); //Thread 수를 센다. }else { logger.error("http reqeust has failed"); } } }); }