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");
}
}
});
}