nu.yona.server.rest.RestClientErrorHandler.java Source code

Java tutorial

Introduction

Here is the source code for nu.yona.server.rest.RestClientErrorHandler.java

Source

/*******************************************************************************
 * Copyright (c) 2016, 2017 Stichting Yona Foundation This Source Code Form is subject to the terms of the Mozilla Public License, v.
 * 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *******************************************************************************/
package nu.yona.server.rest;

import java.io.IOException;
import java.io.InputStream;
import java.util.Optional;
import java.util.Scanner;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.web.client.ResponseErrorHandler;

import com.fasterxml.jackson.databind.ObjectMapper;

import nu.yona.server.exceptions.UpstreamException;
import nu.yona.server.exceptions.YonaException;

/**
 * This handler just logs any REST client errors that occur. When this handler is configured on a REST template, callers are
 * responsible for explicitly checking the error status. This enables them to fetch data that is included in the error response
 * (in the Yona case: the code and message).
 */
public class RestClientErrorHandler implements ResponseErrorHandler {
    private static final Logger logger = LoggerFactory.getLogger(RestClientErrorHandler.class);
    private final ObjectMapper objectMapper;

    public RestClientErrorHandler(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    @Override
    public void handleError(ClientHttpResponse response) throws IOException {
        logger.error("Response error: {} {}", getStatusCode(response), response.getStatusText());
        Optional<ErrorResponseDto> yonaErrorResponse = getYonaErrorResponse(response);
        yonaErrorResponse.ifPresent(yer -> {
            throw UpstreamException.yonaException(getStatusCode(response), yer.getCode(), yer.getMessage());
        });
        throw UpstreamException.remoteServiceError(getStatusCode(response),
                convertStreamToString(response.getBody()));
    }

    @Override
    public boolean hasError(ClientHttpResponse response) throws IOException {
        return RestUtil.isError(getStatusCode(response));
    }

    private HttpStatus getStatusCode(ClientHttpResponse response) {
        try {
            return response.getStatusCode();
        } catch (IOException e) {
            throw YonaException.unexpected(e);
        }
    }

    private Optional<ErrorResponseDto> getYonaErrorResponse(ClientHttpResponse response) {
        try {
            if (getStatusCode(response).series() == HttpStatus.Series.CLIENT_ERROR) {
                return Optional.ofNullable(objectMapper.readValue(response.getBody(), ErrorResponseDto.class));
            }
        } catch (IOException e) {
            // Ignore and just return empty
        }
        return Optional.empty();
    }

    private static String convertStreamToString(InputStream is) {
        @SuppressWarnings("resource") // It's not on us to close this stream
        java.util.Scanner s = new Scanner(is).useDelimiter("\\A");
        return s.hasNext() ? s.next() : "";
    }
}