Skip to content
Advertisement

How to handle UnsupportedMediaTypeException in Spring Boot?

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

    });
}
User contributions licensed under: CC BY-SA
1 People found this is helpful
Advertisement